/**
 @file sys_usw_mirror.c

 @date 2009-10-21

 @version v2.0
*/

/****************************************************************************
 *
* Header Files
*
****************************************************************************/
#include "ctc_error.h"
#include "ctc_common.h"
#include "ctc_const.h"
#include "ctc_packet.h"

#include "sys_usw_common.h"
#include "sys_usw_mirror.h"
#include "sys_usw_port_api.h"
#include "sys_usw_internal_port.h"
#include "sys_usw_vlan.h"
#include "sys_usw_nexthop_api.h"
#include "sys_usw_nexthop.h"
#include "sys_usw_qos_api.h"
#include "sys_usw_register.h"
#include "sys_usw_wb_common.h"
#include "sys_usw_linkagg.h"

#include "drv_api.h"
#include "usw/include/drv_common.h"

/****************************************************************************
 *
* Defines and Macros
*
*****************************************************************************/

#define SYS_MIRROR_INVALID_ILOOP_PORT  0xFFFF
#define SYS_MIRROR_ACLLOG_INGRESS_PRI_NUM 8
#define SYS_MIRROR_ACLLOG_EGRESS_PRI_NUM 3
#define SYS_MIRROR_LINKAGG_MEMBER_NUM 8
#define SYS_REASON_TRUNCATION_GRAN 64
#define SYS_REASON_MAX_TRUNCATED_LEN 960
#define SYS_MIRROR_HASH_SIZE 512
#define SYS_MIRROR_HASH_BLOCK_SIZE 32

#define SYS_MIRROR_INIT_CHECK() \
    do { \
        LCHIP_CHECK(lchip); \
        if (p_usw_mirror_master[lchip] == NULL){ \
            SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " Feature not initialized \n");\
			return CTC_E_NOT_INIT;\
 } \
    } while (0)

#define MIRROR_SET_MAC(d, s)       sal_memcpy(d, s, sizeof(mac_addr_t))
#define MIRROR_SET_HW_MAC(d, s)    SYS_USW_SET_HW_MAC(d, s)

#if 0
#define SYS_MIRROR_TYPE_MAPPING(p_mirror, mirror_type) \
{\
    mirror_type = p_mirror->type;\
    if (p_mirror->type == CTC_MIRROR_ACLLOG_SESSION)\
    {  mirror_type = p_mirror->type + p_mirror->acl_priority; }\
    else if (p_mirror->type > CTC_MIRROR_ACLLOG_SESSION)\
    {  mirror_type = p_mirror->type + MCHIP_CAP(SYS_CAP_MIRROR_ACL_ID) - 1; }\
}
#endif

#define SYS_MIRROR_TYPE_UNMAPPING(p_mirror, mirror_type) \
{\
    p_mirror->type = mirror_type;\
    if (mirror_type >= (CTC_MIRROR_ACLLOG_SESSION + MCHIP_CAP(SYS_CAP_MIRROR_ACL_ID)))\
    {  p_mirror->type = mirror_type - (MCHIP_CAP(SYS_CAP_MIRROR_ACL_ID) - 1); }\
    else if (mirror_type >= CTC_MIRROR_ACLLOG_SESSION)\
    {  p_mirror->type = CTC_MIRROR_ACLLOG_SESSION;\
       p_mirror->acl_priority = mirror_type - CTC_MIRROR_ACLLOG_SESSION; }\
}


#define SYS_MIRROR_ACL_LOG_EXCEPTION_IDX(dir, session_id, priority_id)\
        ((CTC_INGRESS == dir)\
        ? (MCHIP_CAP(SYS_CAP_MIRROR_INGRESS_ACL_LOG_INDEX_BASE) + (priority_id * MAX_CTC_MIRROR_SESSION_ID) + session_id)\
        : (MCHIP_CAP(SYS_CAP_MIRROR_EGRESS_ACL_LOG_INDEX_BASE) + (priority_id * MAX_CTC_MIRROR_SESSION_ID) + session_id))

sys_mirror_master_t* p_usw_mirror_master[CTC_MAX_LOCAL_CHIP_NUM_PP] = {NULL};
/****************************************************************************
 *
* Function
*
*****************************************************************************/
#define __hash_register_function__
STATIC uint32
_sys_usw_mirror_hash_make(sys_mirror_dest_node_t* node)
{
    return ctc_hash_caculate(sizeof(uint32), node);
}

STATIC bool
_sys_usw_mirror_hash_compare(sys_mirror_dest_node_t* node0, sys_mirror_dest_node_t* node1)
{
    if (!node0 || !node1)
    {
        return FALSE;
    }

    if (node0->session_id != node1->session_id
        || node0->type != node1->type
        || node0->dir != node1->dir
        || node0->member_index != node1->member_index)
    {
        return FALSE;
    }

    return TRUE;
}

void
sys_usw_mirror_type_mapping(uint8 ctc_type, uint8 acl_prio, uint8* sys_type)
{
    switch(ctc_type)
    {
    case CTC_MIRROR_L2SPAN_SESSION:
        *sys_type = SYS_MIRROR_L2SPAN_SESSION;
        break;
    case CTC_MIRROR_L3SPAN_SESSION:
        *sys_type = SYS_MIRROR_L3SPAN_SESSION;
        break;
    case CTC_MIRROR_ACLLOG_SESSION:
        *sys_type = SYS_MIRROR_ACLLOG_SESSION+acl_prio;
        break;
    case CTC_MIRROR_CPU_SESSION:
        *sys_type = SYS_MIRROR_CPU_SESSION;
        break;
    case CTC_MIRROR_IPFIX_LOG_SESSION:
        *sys_type = SYS_MIRROR_IPFIX_LOG_SESSION;
        break;
    default:
        break;
    }
}

void
sys_usw_mirror_type_unmapping(uint8 sys_type, uint8* ctc_type, uint8* acl_prio)
{
    switch(sys_type)
    {
    case SYS_MIRROR_L2SPAN_SESSION:
        *ctc_type = CTC_MIRROR_L2SPAN_SESSION;
        break;
    case SYS_MIRROR_L3SPAN_SESSION:
        *ctc_type = CTC_MIRROR_L3SPAN_SESSION;
        break;
    case SYS_MIRROR_CPU_SESSION:
        *ctc_type = CTC_MIRROR_CPU_SESSION;
        break;
    case SYS_MIRROR_IPFIX_LOG_SESSION:
        *ctc_type = CTC_MIRROR_IPFIX_LOG_SESSION;
        break;
    default:
        break;
    }
    if ((sys_type >= SYS_MIRROR_ACLLOG_SESSION) && (sys_type < (SYS_MIRROR_ACLLOG_SESSION + SYS_MIRROR_ACLLOG_SESSION_RSV)))
    {
        *ctc_type = CTC_MIRROR_ACLLOG_SESSION;
        *acl_prio = sys_type - SYS_MIRROR_ACLLOG_SESSION;
    }
}

int32
sys_usw_mirror_update_linkagg_member(uint8 lchip, uint16 tid, uint32* member_list, uint16 member_cnt, uint8 is_set)
{
    int32  ret = CTC_E_NONE;
    SYS_MIRROR_INIT_CHECK();
    MIRROR_LOCK;
    if (MCHIP_MIRROR(lchip)->mirror_update_linkagg_member)
    {
        CTC_ERROR_GOTO(MCHIP_MIRROR(lchip)->mirror_update_linkagg_member(lchip, tid, member_list, member_cnt, is_set), ret, exit);
    }
exit:
    MIRROR_UNLOCK;
    return ret;
}

STATIC bool
_sys_usw_mirror_check_alloced_nexthop(uint8 lchip, uint32 nh_id)
{
    uint32 max_nh = 0;
    int32 ret = 0;
    sys_nh_info_dsnh_t nhinfo;

    sal_memset(&nhinfo, 0, sizeof(nhinfo));
    sys_usw_nh_get_max_external_nhid(lchip, &max_nh);
    ret = sys_usw_nh_get_nhinfo(lchip, nh_id, &nhinfo, 0);
    if (ret < 0)
    {
        return FALSE;
    }

    if (nh_id >= max_nh && SYS_NH_TYPE_BRGUC != nhinfo.nh_entry_type)
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

sys_mirror_dest_node_t*
_sys_usw_mirror_get_db_info(uint8 lchip, ctc_mirror_dest_t* p_mirror, uint8 member_index)
{
    sys_mirror_dest_node_t node_tmp;
    uint8 type = 0;

    sal_memset(&node_tmp, 0, sizeof(sys_mirror_dest_node_t));
    sys_usw_mirror_type_mapping(p_mirror->type, p_mirror->acl_priority, &type);
    node_tmp.type = type;
    node_tmp.session_id = p_mirror->session_id;
    node_tmp.dir = p_mirror->dir;
    node_tmp.member_index = member_index;

    return ((sys_mirror_dest_node_t*)ctc_hash_lookup(p_usw_mirror_master[lchip]->dest_hash, &node_tmp));
}

int32
_sys_usw_mirror_traverse_dest(sys_mirror_dest_node_t* bucket_data, void* user_data)
{
    sys_traverse_t* p_user_data = (sys_traverse_t*)user_data;
    uint16* loop_port = (uint16 *)(p_user_data->data);
    if (bucket_data->nh_id == p_user_data->value1)
    {
        *loop_port = bucket_data->loop_port;
        p_user_data->value2 ++;/*loop_port_num*/
    }
    return CTC_E_NONE;
}

uint8
_sys_usw_mirror_get_loop_port(uint8 lchip, uint32 nh_id, uint16* p_loop_port)
{
    sys_traverse_t user_data;
    sal_memset(&user_data,0,sizeof(sys_traverse_t));
    user_data.value1 = nh_id;
    user_data.data = p_loop_port;

    CTC_ERROR_RETURN(ctc_hash_traverse(p_usw_mirror_master[lchip]->dest_hash, 
                        (hash_traversal_fn)_sys_usw_mirror_traverse_dest, (void*)(&user_data)));
    
    *p_loop_port = *(uint16*)(user_data.data);
    return user_data.value2;/*loop_port_num*/
}

STATIC int32
_sys_usw_mirror_set_loop_port(uint8 lchip, uint32 nh_id, uint32* gport, ctc_mirror_dest_t* p_mirror, uint8 pos)
{
    sys_nh_info_dsnh_t nhinfo;
    uint8  gchip = 0;
    uint16 loop_port = 0;
    uint32 old_nh_id = 0;
    uint8 new_loop_port_ref = 0;
    uint16 new_loop_port = 0;
    ctc_internal_port_assign_para_t port_assign;
    sys_mirror_dest_node_t* dest_node = NULL;

    sal_memset(&nhinfo, 0, sizeof(nhinfo));
    CTC_ERROR_DUMP(sys_usw_nh_get_nhinfo(lchip, nh_id, &nhinfo, 0));
    if ((nhinfo.nh_entry_type != SYS_NH_TYPE_ILOOP) && (nhinfo.nh_entry_type != SYS_NH_TYPE_MCAST))
    {
        return CTC_E_NONE;
    }

    /*iloop*/
    if (nhinfo.nh_entry_type == SYS_NH_TYPE_ILOOP)
    {
        if (CTC_IS_BIT_SET(nhinfo.dsnh_offset, 11)
            && ( 7 == ((nhinfo.dsnh_offset >> 12) & 0x7)))
        {
            loop_port = (nhinfo.dsnh_offset & 0x7F) | (((nhinfo.dsnh_offset >> 16)&0x1) << 7);
            sys_usw_port_api_set_mirror_en(lchip, loop_port, 0, 0, 1);
        }
    }
    /*mcast*/
    else
    {
        sys_usw_get_gchip_id(lchip, &gchip);
        if (DRV_FROM_TMM(lchip))
        {
            loop_port = SYS_RSV_PORT_E2ILOOP_ID;
        }
        else
        {
            dest_node = _sys_usw_mirror_get_db_info(lchip, p_mirror, pos);
            if (NULL != dest_node)
            {
                old_nh_id = dest_node->nh_id;
            }

            new_loop_port_ref = _sys_usw_mirror_get_loop_port(lchip, nh_id, &new_loop_port);
            if ((old_nh_id != nh_id) && (0 == new_loop_port_ref))
            {
                sal_memset(&port_assign, 0, sizeof(port_assign));
                port_assign.type = CTC_INTERNAL_PORT_TYPE_ELOOP;
                port_assign.gchip = gchip;
                port_assign.nhid = nh_id;

                CTC_ERROR_RETURN(sys_usw_internal_port_allocate(lchip, &port_assign));
                loop_port = port_assign.inter_port;
                SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "alloc internal port:%d\n", loop_port);
            }
            else if (old_nh_id != nh_id)
            {
                loop_port = new_loop_port;
            }
        }

        *gport  = CTC_MAP_LPORT_TO_GPORT(gchip, loop_port);
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_mirror_unset_loop_port(uint8 lchip, ctc_mirror_dest_t *p_mirror, uint8 pos)
{
    uint8 old_loop_port_ref = 0;
    uint16 loop_port = 0;
    sys_mirror_dest_node_t* dest_node = NULL;
    sys_nh_info_dsnh_t nhinfo;

    dest_node = _sys_usw_mirror_get_db_info(lchip, p_mirror, pos);

    if (NULL == dest_node)
    {
        return CTC_E_NONE;
    }

    if ((SYS_MIRROR_RSPAN_OVER_VLAN == dest_node->data_type || SYS_MIRROR_RSPAN_OVER_LINKAGG == dest_node->data_type)
        && _sys_usw_mirror_check_alloced_nexthop(lchip, dest_node->nh_id))
    {
        /* delete old internal nh */
        CTC_ERROR_RETURN(sys_usw_rspan_nh_delete(lchip, dest_node->nh_id));
    }
    else if(SYS_MIRROR_RSPAN_OVER_ILOOP == dest_node->data_type)
    {
        old_loop_port_ref = _sys_usw_mirror_get_loop_port(lchip, dest_node->nh_id, &loop_port);    
        if (old_loop_port_ref <= 1)
        {
            sal_memset(&nhinfo, 0, sizeof(nhinfo));
            CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo(lchip, dest_node->nh_id, &nhinfo, 0));
            if (CTC_IS_BIT_SET(nhinfo.dsnh_offset, 11) && ( 7 == ((nhinfo.dsnh_offset >> 12) & 0x7)))
            {
                loop_port = (nhinfo.dsnh_offset & 0x7F) | (((nhinfo.dsnh_offset >> 16)&0x1) << 7);
                sys_usw_port_api_set_mirror_en(lchip, loop_port, 0, 0, 0);
            } 
        }
    }
    else if(SYS_MIRROR_RSPAN_OVER_MCAST == dest_node->data_type)
    {
        /* release old loop_port */
        ctc_internal_port_assign_para_t port_assign;
        sal_memset(&port_assign, 0, sizeof(ctc_internal_port_assign_para_t));
        old_loop_port_ref = _sys_usw_mirror_get_loop_port(lchip, dest_node->nh_id, &loop_port);
        if (old_loop_port_ref <= 1 && !DRV_FROM_TMM(lchip))
        {
            uint8 gchip = 0;
            sys_usw_get_gchip_id(lchip, &gchip);
            port_assign.type = CTC_INTERNAL_PORT_TYPE_ELOOP;
            port_assign.gchip = gchip;
            port_assign.nhid = dest_node->nh_id;
            port_assign.inter_port = loop_port;
            CTC_ERROR_RETURN(sys_usw_internal_port_release(lchip, &port_assign));
        }
    }

    return CTC_E_NONE;
}

/*
 @brief This function is to write chip to set the destination port
*/
STATIC int32
_sys_usw_mirror_set_dest_write_chip(uint8 lchip, uint32 excp_index, uint32 dest_gport, uint32 nh_ptr, ctc_mirror_dest_t* p_mirror)
{
    uint8  gchip_id = 0;
    uint16 lport = 0;
    uint32 destmap = 0;
    uint32 cmd = 0;
    uint8  profile_id = 0;
    uint16  sub_queue_id = 0;
    uint8  member_cnt = 0;
    uint32 member_list[SYS_MIRROR_LINKAGG_MEMBER_NUM] = {0};
    uint8 local_gchip = 0;
    DsMetFifoExcp_m met_excp;
    ds_t hdradj_exp;
    uint32 tbl_id = DRV_FROM_TMM(lchip)? EpeHdrAdjExcp_t: DsBufRetrvExcp_t;
    sys_nh_info_dsnh_t sys_nh_info_dsnh;

    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    sal_memset(&sys_nh_info_dsnh, 0, sizeof(sys_nh_info_dsnh_t));
    sal_memset(&met_excp, 0, sizeof(DsMetFifoExcp_m));
    sal_memset(&hdradj_exp, 0, sizeof(ds_t));

    cmd = DRV_IOR(DsMetFifoExcp_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd, &met_excp));

    destmap = SYS_ENCODE_DESTMAP( gchip_id, SYS_RSV_PORT_DROP_ID);
    SetDsMetFifoExcp(V, destMap_f, &met_excp, destmap);
    SetDsMetFifoExcp(V, u_g0_destSgmacGroupId_f, &met_excp, 0);

    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index , cmd, &hdradj_exp));

    sys_usw_get_gchip_id(lchip, &local_gchip);
    SetEpeHdrAdjExcp(V, truncateLenProfId_f, &hdradj_exp, profile_id);
    SetEpeHdrAdjExcp(V, destMapKeepMode_f, &hdradj_exp, 0);
    
    if(DRV_FROM_AT(lchip))
    {
        SetEpeHdrAdjExcp(V, keepPacketHeaderToRemoteCpu_f, hdradj_exp, 1);
        /*for arctic, cpu tx packet for 1:n mirror all add vlan edit */
        if ((excp_index>>3) == MCHIP_CAP(SYS_CAP_MIRROR_CPU_TX_SPAN_INDEX))
        {
            SetEpeHdrAdjExcp(V, resetPacketOffset_f, &hdradj_exp, 0);
        }
        else
        {
            SetEpeHdrAdjExcp(V, resetPacketOffset_f, &hdradj_exp, 1);
        }
        
    }
    lport = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(dest_gport);
    if (CTC_IS_LINKAGG_PORT(dest_gport))
    {
        SetEpeHdrAdjExcp(V, forceEgressEdit_f, &hdradj_exp, CTC_IS_BIT_SET(nh_ptr, 30));
        SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "excp_index = %d, dest_gport = %d, nh_ptr = %d\n", excp_index, dest_gport, nh_ptr&0x3FFFFFFF);
        if (MCHIP_MIRROR(lchip)->mirror_set_dst_to_linkagg)
        {
            /*destmap = SYS_ENCODE_MIRROR_DESTMAP(CTC_LINKAGG_CHIPID, CTC_GPORT_LINKAGG_ID(dest_gport));*loop*/
            /*SetDsMetFifoExcp(V, destMap_f, &met_excp, SYS_RSV_PORT_E2ILOOP_ID);*loop*/
            /*SetDsEpeHdrAdjExcp(V, destMapKeepMode_f, &hdradj_exp, 1);*loop*/
            /*SetDsEpeHdrAdjExcp(V, destMap_f, &hdradj_exp, destmap);*loop*/
            member_cnt = SYS_MIRROR_LINKAGG_MEMBER_NUM;
            CTC_ERROR_RETURN(sys_usw_linkagg_get_ports2(lchip, CTC_GPORT_LINKAGG_ID(dest_gport), member_list, &member_cnt));
            SetDsMetFifoExcp(V, destMap_f, &met_excp, 0);
            CTC_ERROR_RETURN(MCHIP_MIRROR(lchip)->mirror_set_dst_to_linkagg(lchip, &met_excp, member_list, member_cnt, 1));
            SetEpeHdrAdjExcp(V, destMapKeepMode_f, &hdradj_exp, 0);   /*no loop*/
            CTC_ERROR_RETURN(sys_usw_linkagg_bind_mirror(lchip,  CTC_GPORT_LINKAGG_ID(dest_gport), 1));
        }
        else
        {
            destmap = SYS_ENCODE_MIRROR_DESTMAP(CTC_LINKAGG_CHIPID, CTC_GPORT_LINKAGG_ID(dest_gport));
            SetDsMetFifoExcp(V, destMap_f, &met_excp, destmap);
        }

        SetDsMetFifoExcp(V, nextHopExt_f, &met_excp, CTC_IS_BIT_SET(nh_ptr, 31));
        SetDsMetFifoExcp(V, isSpanPkt_f, &met_excp, 1);

        SetEpeHdrAdjExcp(V, nextHopPtr_f, &hdradj_exp, nh_ptr);
        SetEpeHdrAdjExcp(V, resetPacketHeaderU1_f, &hdradj_exp, 1);
        SetEpeHdrAdjExcp(V, isSpanPkt_f, &hdradj_exp, 1);
        SetEpeHdrAdjExcp(V, resetPacketHeaderToNormal_f, &hdradj_exp, 1);

        if (0 != p_mirror->truncated_len)
        {
            CTC_ERROR_RETURN(sys_usw_register_get_truncation_profile_id(lchip, p_mirror->truncated_len, sizeof(p_mirror->truncated_len)*CTC_UINT8_BITS, &profile_id));
            SetEpeHdrAdjExcp(V, truncateLenProfId_f, &hdradj_exp, profile_id);
        }
    }
    else
    {
        if (MCHIP_MIRROR(lchip)->mirror_set_dst_to_linkagg)
        {
            sys_mirror_dest_node_t* dest_node = NULL;
            dest_node = _sys_usw_mirror_get_db_info(lchip, p_mirror, excp_index % MCHIP_CAP(SYS_CAP_MIRROR_MEMBER_NUM));
            if (dest_node && (SYS_MIRROR_SPAN_OVER_LINKAGG == dest_node->data_type || SYS_MIRROR_RSPAN_OVER_LINKAGG == dest_node->data_type))
            {
                MCHIP_MIRROR(lchip)->mirror_set_dst_to_linkagg(lchip, &met_excp, member_list, member_cnt, 0);
                CTC_ERROR_RETURN(sys_usw_linkagg_bind_mirror(lchip, dest_node->linkagg_id, 0));
            }
        }
        gchip_id = SYS_MAP_CTC_GPORT_TO_GCHIP(dest_gport);

        if (SYS_RSV_PORT_DROP_ID == lport)
        {
            destmap = SYS_ENCODE_DESTMAP(local_gchip, SYS_RSV_PORT_DROP_ID);
        }
        else if (CTC_IS_CPU_PORT(dest_gport))
        {
            CTC_ERROR_RETURN(sys_usw_get_sub_queue_id_by_cpu_reason(lchip, CTC_PKT_CPU_REASON_MIRRORED_TO_CPU, &sub_queue_id));
            destmap = SYS_ENCODE_EXCP_DESTMAP(gchip_id, sub_queue_id);
            if (DRV_FROM_TMM(lchip) && (((dest_gport >> CTC_TYPE_PORT_OFFSET) & CTC_TYPE_PORT_MASK) == CTC_GPORT_TYPE_CPU_MAC))
            {
                uint8  cpu_mac_id = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(dest_gport)&0x3;
                destmap = SYS_ENCODE_DESTMAP_CPU_MAC(gchip_id, cpu_mac_id);
            }
            if (!p_mirror->is_rspan)
            {
                nh_ptr = CTC_PKT_CPU_REASON_BUILD_NHPTR(CTC_PKT_CPU_REASON_MIRRORED_TO_CPU, 0);
            }
        }
        else
        {
            destmap = SYS_ENCODE_MIRROR_DESTMAP(gchip_id, lport);
        }

        SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "excp_index = %d, dest_gport = %d, nh_ptr = %d\n", excp_index, dest_gport, nh_ptr&0x3FFFFFFF);

        SetEpeHdrAdjExcp(V, forceEgressEdit_f, &hdradj_exp, CTC_IS_BIT_SET(nh_ptr, 30));

        if ((!sys_usw_chip_is_local(lchip, gchip_id)) && (DRV_FROM_TMM(lchip)))
        {
            uint8 trunk_id = 0;
            SYS_CB(SYS_CB_STK_GET_TRUNK_BY_RCHIP, lchip, gchip_id, &trunk_id);
            SetDsMetFifoExcp(V, u_g0_destSgmacGroupId_f, &met_excp, trunk_id);
        }
        SetDsMetFifoExcp(V, destMap_f, &met_excp, destmap);
        SetDsMetFifoExcp(V, nextHopExt_f, &met_excp, CTC_IS_BIT_SET(nh_ptr, 31));
        SetDsMetFifoExcp(V, isSpanPkt_f, &met_excp, 1);
        SetEpeHdrAdjExcp(V, nextHopPtr_f, &hdradj_exp, nh_ptr);
        SetEpeHdrAdjExcp(V, resetPacketHeaderU1_f, &hdradj_exp, 1);
        SetEpeHdrAdjExcp(V, isSpanPkt_f, &hdradj_exp, 1);
        SetEpeHdrAdjExcp(V, resetPacketHeaderToNormal_f, &hdradj_exp, 1);

        if(DRV_FROM_TMM(lchip) && p_mirror->is_rspan && !p_mirror->vlan_valid)
        {
            CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo(lchip, p_mirror->rspan.nh_id, &sys_nh_info_dsnh, 0));
            if(SYS_DESTMAP_IS_MCAST(sys_nh_info_dsnh.dest_map))
            {
                SetEpeHdrAdjExcp(V, destMapKeepMode_f, &hdradj_exp, 1);
                SetEpeHdrAdjExcp(V, destMap_f, &hdradj_exp, sys_nh_info_dsnh.dest_map);
            }
            if ((SYS_NH_TYPE_ILOOP == sys_nh_info_dsnh.nh_entry_type))
            {
                SetEpeHdrAdjExcp(V, resetPacketHeaderU1_f, &hdradj_exp, 0);
                SetEpeHdrAdjExcp(V, keepCategoryHeaderOp_f, &hdradj_exp, 1);
            }
        }
        /*To CPU need to forceEgressEdit*/
        if (CTC_IS_CPU_PORT(dest_gport))
        {
            SetEpeHdrAdjExcp(V, forceEgressEdit_f, &hdradj_exp, 1);
            SetEpeHdrAdjExcp(V, resetPacketHeaderU1_f, &hdradj_exp, 0);
            SetEpeHdrAdjExcp(V, keepCategoryHeaderOp_f, &hdradj_exp, 1);
        }

        if (0 != p_mirror->truncated_len)
        {   /*To CPU truncation: TMM not support, D2&TM support */
            if (CTC_IS_CPU_PORT(dest_gport) && !DRV_FROM_TMM(lchip))
            {
                profile_id = (p_mirror->truncated_len + SYS_REASON_TRUNCATION_GRAN -1)/SYS_REASON_TRUNCATION_GRAN;
                SetEpeHdrAdjExcp(V, truncateLenProfId_f, &hdradj_exp, profile_id);
            }
            else
            {
                CTC_ERROR_RETURN(sys_usw_register_get_truncation_profile_id(lchip, p_mirror->truncated_len, sizeof(p_mirror->truncated_len)*CTC_UINT8_BITS, &profile_id));
                SetEpeHdrAdjExcp(V, truncateLenProfId_f, &hdradj_exp, profile_id);
            }
        }
    }
    if(SYS_DESTMAP_IS_MCAST(sys_nh_info_dsnh.dest_map) || SYS_NH_TYPE_ILOOP == sys_nh_info_dsnh.nh_entry_type)
    {
        /*write DsBufRetrvExcp_t table, 0 is slice 0, 1 is slice 1*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd, &hdradj_exp));

        /*Must write DsMetFifoExcp_t table AFTER write BufRetrvExcp*/
        cmd = DRV_IOW(DsMetFifoExcp_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd, &met_excp));

    }
    else
    {
        /*Must write DsMetFifoExcp_t table AFTER write BufRetrvExcp*/
        cmd = DRV_IOW(DsMetFifoExcp_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd, &met_excp));

        /*write DsBufRetrvExcp_t table, 0 is slice 0, 1 is slice 1*/
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd, &hdradj_exp));
    }

    return CTC_E_NONE;
}

int32
sys_usw_mirror_update_trunk_by_rchip(uint8 lchip, uint8 remote_gchip, uint8 trunk_id)
{
    int32  ret = CTC_E_NONE;
    uint8  session_id = 0, session_type = 0, dir = 0;
    uint8  ctc_session_type = 0, acl_prio = 0, loop = 0;
    uint32 excp_index = 0;
    uint32 cmd = 0;
    DsMetFifoExcp_m met_excp;
    ctc_mirror_dest_t mirror;

    SYS_MIRROR_INIT_CHECK();
    MIRROR_LOCK;
    for (session_type=0; session_type<MAX_SYS_MIRROR_SESSION_TYPE; session_type++)
    {
        for (session_id=0; session_id<MAX_CTC_MIRROR_SESSION_ID; session_id++)
        {
            mirror.session_id = session_id;
            for (dir=CTC_INGRESS; dir<CTC_BOTH_DIRECTION; dir++)
            {
                mirror.dir = dir;
                sys_usw_mirror_type_unmapping(session_type, &ctc_session_type, &acl_prio);
                mirror.type = ctc_session_type;
                mirror.acl_priority = acl_prio;
                ret = sys_usw_mirror_mapping_excp_index(lchip, &mirror, &excp_index, 0);
                if (ret != CTC_E_NONE)
                {
                    continue;
                }
                cmd = DRV_IOR(DsMetFifoExcp_t, DRV_ENTRY_FLAG);
                CTC_ERROR_GOTO(DRV_IOCTL(lchip, excp_index, cmd, &met_excp), ret, exit);

                if(GetDsMetFifoExcp(V, unionDestType_f, &met_excp))
                {
                    uint8 step = DsMetFifoExcp_u_g1_member1_u_g1_chipId_f - DsMetFifoExcp_u_g1_member0_u_g1_chipId_f;
                    for(loop=0; loop < 8;loop++)
                    {
                        if(GetDsMetFifoExcp(V, u_g1_member0_u_g1_chipId_f+step*loop, &met_excp) == remote_gchip)
                        {
                            SetDsMetFifoExcp(V, u_g1_destSgmacGroupId0_f+loop, &met_excp, trunk_id);
                        }
                    }
                }
                else
                {
                    if(SYS_DECODE_DESTMAP_GCHIP(GetDsMetFifoExcp(V, destMap_f, &met_excp)) == remote_gchip)
                    {
                        SetDsMetFifoExcp(V, u_g0_destSgmacGroupId_f, &met_excp, trunk_id);
                    }
                }
                cmd = DRV_IOW(DsMetFifoExcp_t, DRV_ENTRY_FLAG);
                CTC_ERROR_GOTO(DRV_IOCTL(lchip, excp_index, cmd, &met_excp), ret, exit);
            }
        }
    }
exit:
    MIRROR_UNLOCK;
    return ret;
}

int32
_sys_usw_mirror_traverse_dump_db(sys_mirror_dest_node_t* bucket_data, void* user_data)
{
    sys_mirror_dest_node_t* dest_node = (sys_mirror_dest_node_t*)bucket_data;
    sal_file_t p_f = (sal_file_t)(((sys_traverse_t*)user_data)->data);
#ifdef CTC_SHELL_DEBUG_ON
    uint8 lchip = (((sys_traverse_t*)user_data)->value1);
#endif

    SYS_DUMP_DB_LOG(p_f, "%s\n", "--------------------------------------------------------------------------------------------------------");
    SYS_DUMP_DB_LOG(p_f, "%-15s%-15s%-15s%-15s%-15s%-15s%-15s\n", "session_id", "type", "direction", "member_index", "mirror_nh", "loop_port", "linkagg_id");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "--------------------------------------------------------------------------------------------------------");
    if (0 != dest_node->nh_id)
    {
        SYS_DUMP_DB_LOG(p_f, "%-15u%-15u%-15u%-15u%-15u%-15s%-15s\n", dest_node->session_id, dest_node->type, dest_node->dir, dest_node->member_index, dest_node->nh_id, "---","---");
    }
    if (0 != dest_node->loop_port)
    {
        SYS_DUMP_DB_LOG(p_f, "%-15u%-15u%-15u%-15u%-15s%-15u%-15s\n", dest_node->session_id, dest_node->type, dest_node->dir, dest_node->member_index, "---", dest_node->loop_port,"---");
    }
    if (SYS_MIRROR_SPAN_OVER_LINKAGG == dest_node->data_type || SYS_MIRROR_RSPAN_OVER_LINKAGG == dest_node->data_type)
    {
        SYS_DUMP_DB_LOG(p_f, "%-15u%-15u%-15u%-15u%-15s%-15s%-15u\n", dest_node->session_id, dest_node->type, dest_node->dir, dest_node->member_index, "---","---",dest_node->linkagg_id);
    }
    return CTC_E_NONE;
}

int32
sys_usw_mirror_dump_db(uint8 lchip, sal_file_t p_f,ctc_global_dump_db_t* p_dump_param)
{
    sys_traverse_t user_data;
    user_data.value1 = lchip;
    user_data.data = (void*)p_f;
    SYS_MIRROR_INIT_CHECK();
    SYS_DUMP_DB_LOG(p_f, "%s\n", "# Mirror");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "{");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "Master config:");
    
    ctc_hash_traverse(p_usw_mirror_master[lchip]->dest_hash, 
                             (hash_traversal_fn)_sys_usw_mirror_traverse_dump_db, (void*)(&user_data));
    SYS_DUMP_DB_LOG(p_f, "\n");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "}");

    return CTC_E_NONE;
}

int32
_sys_usw_mirror_wb_sync_traverse(void* bucket_data, void* user_data)
{
    uint32 max_entry_cnt = 0;
    ctc_wb_data_t *wb_data = NULL;
    sys_wb_mirror_dest_t* p_wb_mirror_dest = NULL;
    sys_mirror_dest_node_t* dest_node = NULL;

    dest_node = (sys_mirror_dest_node_t*)bucket_data;
    wb_data = (ctc_wb_data_t*)user_data;
    max_entry_cnt = wb_data->buffer_len / (wb_data->key_len + wb_data->data_len);

    p_wb_mirror_dest = (sys_wb_mirror_dest_t *)(wb_data->buffer) + wb_data->valid_cnt;

    p_wb_mirror_dest->session_id = dest_node->session_id;
    p_wb_mirror_dest->type = dest_node->type;
    p_wb_mirror_dest->dir = dest_node->dir;
    p_wb_mirror_dest->member_index = dest_node->member_index;
    p_wb_mirror_dest->data_type = dest_node->data_type;
    p_wb_mirror_dest->nh_id = dest_node->nh_id;
    p_wb_mirror_dest->loop_port = dest_node->loop_port;
    p_wb_mirror_dest->linkagg_id = dest_node->linkagg_id;
    if (++wb_data->valid_cnt == max_entry_cnt)
    {
        CTC_ERROR_RETURN(ctc_wb_add_entry(wb_data));
        wb_data->valid_cnt = 0;
    }


    return CTC_E_NONE;
}

int32
sys_usw_mirror_wb_sync(uint8 lchip,uint32 app_id)
{
    int32 ret = CTC_E_NONE;
    ctc_wb_data_t wb_data = {0};
    sys_wb_mirror_master_t* p_wb_mirror_master = NULL;

    /*sync up mirror dest*/
    CTC_WB_ALLOC_BUFFER(&wb_data.buffer);
    MIRROR_LOCK;
    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_MIRROR_SUBID_MASTER)
    {
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_mirror_master_t, CTC_FEATURE_MIRROR, SYS_WB_APPID_MIRROR_SUBID_MASTER);
        p_wb_mirror_master = (sys_wb_mirror_master_t*)wb_data.buffer;
        p_wb_mirror_master->lchip = lchip;
        p_wb_mirror_master->version = SYS_WB_VERSION_MIRROR;


        wb_data.valid_cnt = 1;
        CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_MIRROR, SYS_WB_APPID_MIRROR_SUBID_MASTER);
    }

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_MIRROR_SUBID_DEST)
    {
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_mirror_dest_t, CTC_FEATURE_MIRROR, SYS_WB_APPID_MIRROR_SUBID_DEST);
        CTC_ERROR_GOTO(ctc_hash_traverse(p_usw_mirror_master[lchip]->dest_hash, (hash_traversal_fn)_sys_usw_mirror_wb_sync_traverse, (void*)(&wb_data)), ret, done);

        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_MIRROR, SYS_WB_APPID_MIRROR_SUBID_DEST);
    }

done:
      MIRROR_UNLOCK;
      CTC_WB_FREE_BUFFER(wb_data.buffer);

    return ret;
}

int32
_sys_usw_mirror_wb_init(uint8 lchip)
{
   ctc_wb_appid_t  appid;
   sal_memset(&appid,0,sizeof(appid));

   appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_MIRROR, SYS_WB_APPID_MIRROR_SUBID_MASTER) ;
   appid.entry_num = 1;
   appid.entry_size  = sizeof(sys_wb_mirror_master_t);
   ctc_wb_add_appid( lchip, &appid);

   appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_MIRROR, SYS_WB_APPID_MIRROR_SUBID_DEST) ;
   appid.entry_num = MAX_CTC_MIRROR_SESSION_ID * MAX_SYS_MIRROR_SESSION_TYPE * CTC_BOTH_DIRECTION * MCHIP_CAP(SYS_CAP_MIRROR_MEMBER_NUM);
   appid.entry_size  = sizeof(sys_wb_mirror_dest_t);
   ctc_wb_add_appid( lchip, &appid);

   return 0;
}


int32
sys_usw_mirror_wb_restore(uint8 lchip)
{
    int32 ret = CTC_E_NONE;
    ctc_wb_query_t wb_query;
    sys_wb_mirror_dest_t* p_wb_mirror_dest;
    sys_wb_mirror_master_t wb_mirror_master;
    uint32 entry_cnt = 0;
    ds_t ds_excp;
    sys_mirror_dest_node_t* dest_node = NULL;

    CTC_WB_ALLOC_BUFFER(&wb_query.buffer);
    sal_memset(&ds_excp, 0, sizeof(ds_t));

    /*restore master*/
    /* set default value to new added fields, default value may not be zeros */
    sal_memset(&wb_mirror_master, 0, sizeof(sys_wb_mirror_master_t));
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_mirror_master_t, CTC_FEATURE_MIRROR, SYS_WB_APPID_MIRROR_SUBID_MASTER);
    CTC_ERROR_GOTO(ctc_wb_query_entry(&wb_query), ret, done);
    if (wb_query.valid_cnt != 1 || wb_query.is_end != 1)
    {
        CTC_WB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "query mirror master error! valid_cnt: %d, is_end: %d.\n", wb_query.valid_cnt, wb_query.is_end);
        ret = CTC_E_NONE;
        goto done;
    }
    sal_memcpy((uint8*)&wb_mirror_master, (uint8*)(wb_query.buffer) + entry_cnt * (wb_query.key_len + wb_query.data_len), wb_query.key_len + wb_query.data_len);
    if CTC_WB_VERSION_CHECK(SYS_WB_VERSION_MIRROR, wb_mirror_master.version)
    {
        ret = CTC_E_VERSION_MISMATCH;
        goto done;
    }

    /*restore mirror dest*/
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_mirror_dest_t, CTC_FEATURE_MIRROR, SYS_WB_APPID_MIRROR_SUBID_DEST);
    entry_cnt = 0;
    CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
        p_wb_mirror_dest = (sys_wb_mirror_dest_t*)wb_query.buffer + entry_cnt++;/*after reading entry from sqlite, wb_query.buffer is still the first address of the space*/

        dest_node = mem_malloc(MEM_MIRROR_MODULE, sizeof(sys_mirror_dest_node_t));
        if(NULL == dest_node)
        {
            ret = CTC_E_NO_MEMORY;
            goto done;
        }
        sal_memset(dest_node, 0, sizeof(sys_mirror_dest_node_t));

        dest_node->session_id = p_wb_mirror_dest->session_id;
        dest_node->type = p_wb_mirror_dest->type;
        dest_node->dir = p_wb_mirror_dest->dir;
        dest_node->member_index = p_wb_mirror_dest->member_index;
        dest_node->data_type = p_wb_mirror_dest->data_type;
        dest_node->nh_id = p_wb_mirror_dest->nh_id;
        dest_node->loop_port = p_wb_mirror_dest->loop_port;
        dest_node->linkagg_id = p_wb_mirror_dest->linkagg_id;

        if (0 != p_wb_mirror_dest->linkagg_id)
        {
            sys_usw_linkagg_bind_mirror(lchip, p_wb_mirror_dest->linkagg_id, 1);
        }

        if (NULL == ctc_hash_insert(p_usw_mirror_master[lchip]->dest_hash, dest_node))
        {
            mem_free(dest_node);
            ret = CTC_E_NO_MEMORY;
            goto done;
        }

    CTC_WB_QUERY_ENTRY_END((&wb_query));
done:
    if (wb_query.key)
    {
        mem_free(wb_query.key);
    }

    CTC_WB_FREE_BUFFER(wb_query.buffer);
    return ret;
}

/*
 @brief This function is to initialize the mirror module
*/
int32
sys_usw_mirror_init(uint8 lchip)
{
    uint8  session_id = 0;
    uint8  gchip_id = 0;
    uint32 cmd1 = 0;
    uint32 cmd2 = 0;
    uint32 excp_index = 0;
    uint32 nh_ptr = 0;
    uint32 cmd = 0;
    uint32 dest_map = 0;
    int32  ret = CTC_E_NONE;
    hw_mac_addr_t mac_addr;
    DsMetFifoExcp_m met_excp;
    EpeMirrorEscapeCam_m mirror_escape;
    BufferStoreCtl_m buffer_store_ctl;
    IpeCpuRxTxExceptionCtl_m  ipe_cpurxtxexception_ctl;
    ds_t hdradj_exp;
    uint32 tbl_id = DRV_FROM_TMM(lchip)? EpeHdrAdjExcp_t : DsBufRetrvExcp_t;
    uint8 bit_width = DRV_FROM_AT(lchip)? 3 : 0;
  /*   BufStoreChanIdCfg_m buf_store_chan_id_cfg;*/
    EpeNextHopCtl_m ctl;
    EpeHdrAdjustCtl_m adjustctl;

    if (p_usw_mirror_master[lchip])
    {
        return CTC_E_NONE;
    }
    SYS_VCHIP_MASTER_INIT(lchip, p_usw_mirror_master, CTC_FEATURE_MIRROR);

    sal_memset(&met_excp, 0, sizeof(DsMetFifoExcp_m));
    sal_memset(&hdradj_exp, 0, sizeof(ds_t));
    cmd1 = DRV_IOW(DsMetFifoExcp_t, DRV_ENTRY_FLAG);
    cmd2 = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);

    CTC_ERROR_RETURN(sys_usw_nh_get_resolved_offset(lchip, SYS_NH_RES_OFFSET_TYPE_MIRROR_NH, &nh_ptr));

    sys_usw_get_gchip_id(lchip, &gchip_id);
    dest_map = SYS_ENCODE_DESTMAP( gchip_id, SYS_RSV_PORT_DROP_ID);

    SetDsMetFifoExcp(V, destMap_f, &met_excp, dest_map);
    SetEpeHdrAdjExcp(V, nextHopPtr_f, &hdradj_exp, nh_ptr);
    SetEpeHdrAdjExcp(V, resetPacketOffset_f, &hdradj_exp, 1);
    
    for (session_id = 0; session_id < MAX_CTC_MIRROR_SESSION_ID; session_id++)
    {
        /*port session ingress*/
        excp_index = MCHIP_CAP(SYS_CAP_MIRROR_INGRESS_L2_SPAN_INDEX_BASE) + session_id;
        excp_index <<= bit_width;
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd1, &met_excp));
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd2, &hdradj_exp));

        /*port session egress*/
        excp_index = MCHIP_CAP(SYS_CAP_MIRROR_EGRESS_L2_SPAN_INDEX_BASE) + session_id;
        excp_index <<= bit_width;
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd1, &met_excp));
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd2, &hdradj_exp));

        /*vlan session ingress*/
        excp_index = MCHIP_CAP(SYS_CAP_MIRROR_INGRESS_L3_SPAN_INDEX_BASE) + session_id;
        excp_index <<= bit_width;
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd1, &met_excp));
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd2, &hdradj_exp));

        /*vlan session egress*/
        excp_index = MCHIP_CAP(SYS_CAP_MIRROR_EGRESS_L3_SPAN_INDEX_BASE) + session_id;
        excp_index <<= bit_width;
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd1, &met_excp));
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd2, &hdradj_exp));

        /*acl session ingress*/
        excp_index = MCHIP_CAP(SYS_CAP_MIRROR_INGRESS_ACL_LOG_INDEX_BASE) + session_id;
        excp_index <<= bit_width;
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd1, &met_excp));
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd2, &hdradj_exp));

        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index + (4 << bit_width), cmd1, &met_excp));
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index + (4 << bit_width), cmd2, &hdradj_exp));

        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index + (8 << bit_width), cmd1, &met_excp));
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index + (8 << bit_width), cmd2, &hdradj_exp));

        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index + (12 << bit_width), cmd1, &met_excp));
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index + (12 << bit_width), cmd2, &hdradj_exp));

        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index + (16 << bit_width), cmd1, &met_excp));
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index + (16 << bit_width), cmd2, &hdradj_exp));

        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index + (20 << bit_width), cmd1, &met_excp));
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index + (20 << bit_width), cmd2, &hdradj_exp));

        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index + (24 << bit_width), cmd1, &met_excp));
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index + (24 << bit_width), cmd2, &hdradj_exp));

        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index + (28 << bit_width), cmd1, &met_excp));
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index + (28 << bit_width), cmd2, &hdradj_exp));

        /*acl session egress*/
        excp_index = MCHIP_CAP(SYS_CAP_MIRROR_EGRESS_ACL_LOG_INDEX_BASE) + session_id;
        excp_index <<= bit_width;
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd1, &met_excp));
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd2, &hdradj_exp));

        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index + (4 << bit_width), cmd1, &met_excp));
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index + (4 << bit_width), cmd2, &hdradj_exp));

        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index + (8 << bit_width), cmd1, &met_excp));
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index + (8 << bit_width), cmd2, &hdradj_exp));
    }


    /*Rx cpu session*/
    excp_index = MCHIP_CAP(SYS_CAP_MIRROR_CPU_RX_SPAN_INDEX);
    excp_index <<= bit_width;
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd1, &met_excp));
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd2, &hdradj_exp));

    /*Tx cpu session*/
    excp_index = MCHIP_CAP(SYS_CAP_MIRROR_CPU_TX_SPAN_INDEX);
    excp_index <<= bit_width;
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd1, &met_excp));
    SetEpeHdrAdjExcp(V, resetPacketOffset_f, &hdradj_exp, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd2, &hdradj_exp));

    p_usw_mirror_master[lchip] = (sys_mirror_master_t*)mem_malloc(MEM_MIRROR_MODULE, sizeof(sys_mirror_master_t));
    if (NULL == p_usw_mirror_master[lchip])
    {
        SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;

    }

    sal_memset(p_usw_mirror_master[lchip], 0, sizeof(sys_mirror_master_t));
    ret = sal_mutex_create(&p_usw_mirror_master[lchip]->p_mutex);
    if (ret || !p_usw_mirror_master[lchip]->p_mutex)
    {
        SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Create mutex fail\n");
        CTC_ERROR_GOTO(CTC_E_NO_MEMORY, ret, error_proc);
    }

    p_usw_mirror_master[lchip]->dest_hash = ctc_hash_create(SYS_MIRROR_HASH_SIZE/SYS_MIRROR_HASH_BLOCK_SIZE,
                                        SYS_MIRROR_HASH_BLOCK_SIZE,
                                        (hash_key_fn) _sys_usw_mirror_hash_make,
                                        (hash_cmp_fn) _sys_usw_mirror_hash_compare);
    if (NULL == p_usw_mirror_master[lchip]->dest_hash)
    {
        SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "No Memory! \n");
        CTC_ERROR_GOTO(CTC_E_NO_MEMORY, ret, error_proc);
    }
    sal_memset(&mirror_escape, 0, sizeof(EpeMirrorEscapeCam_m));
    sal_memset(&mac_addr, 0xFF, sizeof(mac_addr_t));
    SetEpeMirrorEscapeCam(A, array_0_macDaMask_f, &mirror_escape, &mac_addr);
    SetEpeMirrorEscapeCam(A, array_1_macDaMask_f, &mirror_escape, &mac_addr);
    SetEpeMirrorEscapeCam(V, array_0_valid_f, &mirror_escape, 0);
    SetEpeMirrorEscapeCam(V, array_1_valid_f, &mirror_escape, 0);

    cmd = DRV_IOW(EpeMirrorEscapeCam_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &mirror_escape), ret, error_proc);

    if (DRV_FROM_TMM(lchip))
    {
        sal_memset(&ipe_cpurxtxexception_ctl, 0, sizeof(IpeCpuRxTxExceptionCtl_m));
        cmd = DRV_IOR(IpeCpuRxTxExceptionCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ipe_cpurxtxexception_ctl), ret, error_proc);
        SetIpeCpuRxTxExceptionCtl(V, exceptionVectorEgressBitmap_f, &ipe_cpurxtxexception_ctl, 0xD41);/*1101 0100 0001*/
        SetIpeCpuRxTxExceptionCtl(V, exceptionVectorIngressBitmap_f, &ipe_cpurxtxexception_ctl, 0x4A801);/*100 1010 1000 0000 0001*/
        SetIpeCpuRxTxExceptionCtl(V, cpuRxQueueModeEn_f, &ipe_cpurxtxexception_ctl, 1);
        cmd = DRV_IOW(IpeCpuRxTxExceptionCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ipe_cpurxtxexception_ctl), ret, error_proc);
    }
    else
    {
        sal_memset(&buffer_store_ctl, 0, sizeof(BufferStoreCtl_m));
        cmd = DRV_IOR(BufferStoreCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &buffer_store_ctl), ret, error_proc);
        SetBufferStoreCtl(V, exceptionVectorIngressBitmap_f, &buffer_store_ctl, 0x4A801); /*100 1010 1000 0000 0001*/
        SetBufferStoreCtl(V, exceptionVectorEgressBitmap_f, &buffer_store_ctl, 0xD41); /*1101 0100 0001*/
        SetBufferStoreCtl(V, cpuRxQueueModeEn_f, &buffer_store_ctl, 1);
        cmd = DRV_IOW(BufferStoreCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &buffer_store_ctl), ret, error_proc);
    }

    cmd = DRV_IOR(EpeNextHopCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd , &ctl), ret, error_proc);
    SetEpeNextHopCtl(V, symmetricalHashCtl_0_hashEn_f, &ctl, 1);
    SetEpeNextHopCtl(V, symmetricalHashCtl_1_hashEn_f, &ctl, 1);
    cmd = DRV_IOW(EpeNextHopCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd , &ctl), ret, error_proc);

    cmd = DRV_IOR(EpeHdrAdjustCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd , &adjustctl), ret, error_proc);
    SetEpeHdrAdjustCtl(V, keepPacketHeaderToRemoteCpuMode_f, &adjustctl, 1);
    cmd = DRV_IOW(EpeHdrAdjustCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &adjustctl), ret, error_proc);

    CTC_ERROR_GOTO(sys_usw_wb_sync_register_cb(lchip, CTC_FEATURE_MIRROR, SYS_WB_APPID_MIRROR_SUBID_MAX,sys_usw_mirror_wb_sync), ret, error_proc);

    if (CTC_WB_ENABLE(lchip) && CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING)
    {
        CTC_ERROR_GOTO(sys_usw_mirror_wb_restore(lchip), ret, error_proc);
    }
    if (CTC_WB_ENABLE(lchip))
    {
        _sys_usw_mirror_wb_init(lchip);
    }
    CTC_ERROR_GOTO(sys_usw_dump_db_register_cb(lchip, CTC_FEATURE_MIRROR, sys_usw_mirror_dump_db), ret, error_proc);
    CTC_ERROR_GOTO(SYS_CB_REGISTER(lchip, SYS_CB_MIRROR_SET_DST_TO_LINKAGG, sys_usw_mirror_update_linkagg_member), ret, error_proc);
    CTC_ERROR_GOTO(SYS_CB_REGISTER(lchip, SYS_CB_MIRROR_UPDATE_TRUNK_BY_RCHIP, sys_usw_mirror_update_trunk_by_rchip), ret, error_proc);

    CTC_ERROR_RETURN(sys_usw_dump_db_register_cb(lchip, CTC_FEATURE_MIRROR, sys_usw_mirror_dump_db));
    sys_usw_mchip_set_feature_en(lchip,CTC_FEATURE_MIRROR);
    return CTC_E_NONE;
error_proc:
    if(p_usw_mirror_master[lchip]->dest_hash)
    {
        ctc_hash_free(p_usw_mirror_master[lchip]->dest_hash);
    }
    if(p_usw_mirror_master[lchip]->p_mutex)
    {
        sal_mutex_destroy(p_usw_mirror_master[lchip]->p_mutex);
    }
    mem_free(p_usw_mirror_master[lchip]);
    return ret;
}

int32
_sys_usw_mirror_traverse(sys_mirror_dest_node_t* bucket_data, void* user_data)
{
    mem_free(bucket_data);
    return CTC_E_NONE;
}

/*
 @brief This function is to initialize the mirror module
*/
int32
sys_usw_mirror_deinit(uint8 lchip)
{
    LCHIP_CHECK(lchip);

    if (!p_usw_mirror_master[lchip])
    {
        return CTC_E_NONE;
    }
    SYS_VCHIP_MASTER_DEINIT(lchip, p_usw_mirror_master, CTC_FEATURE_MIRROR);
    
    if(p_usw_mirror_master[lchip]->dest_hash)
    {
        ctc_hash_traverse(p_usw_mirror_master[lchip]->dest_hash, (hash_traversal_fn)_sys_usw_mirror_traverse, NULL);
        ctc_hash_free(p_usw_mirror_master[lchip]->dest_hash);
    }
    if (p_usw_mirror_master[lchip]->p_mutex)
    {
        sal_mutex_destroy(p_usw_mirror_master[lchip]->p_mutex);
    }
    sys_usw_wb_sync_register_cb(lchip, CTC_FEATURE_MIRROR,0, NULL);
    sys_usw_dump_db_register_cb(lchip, CTC_FEATURE_MIRROR, NULL);
    SYS_CB_REGISTER(lchip, SYS_CB_MIRROR_SET_DST_TO_LINKAGG, NULL);
    SYS_CB_REGISTER(lchip, SYS_CB_MIRROR_UPDATE_TRUNK_BY_RCHIP, NULL);
    mem_free(p_usw_mirror_master[lchip]);
    return 0;
}

/*
 @brief This function is to set port able to mirror
*/
int32
sys_usw_mirror_set_port_en(uint8 lchip, uint32 gport, ctc_direction_t dir, bool enable, uint8 session_id)
{
    uint16 lport = 0;
    uint32 cmd = 0;
    int32  ret = CTC_E_NONE;
    BufferStoreCtl_m buffer_store_ctl;
    IpeCpuRxTxExceptionCtl_m  ipe_cpurxtxexception_ctl;
    SYS_MIRROR_INIT_CHECK();

    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    MIRROR_LOCK;
    if (CTC_IS_CPU_PORT(gport))
    {
        if (session_id >= 1)
        {
            ret = CTC_E_INVALID_PARAM;
            goto exit;
        }
        sal_memset(&buffer_store_ctl, 0, sizeof(BufferStoreCtl_m));
        cmd = DRV_IOR(BufferStoreCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &buffer_store_ctl),ret,exit);
        if ((dir == CTC_INGRESS) || (dir == CTC_BOTH_DIRECTION))
        {
            SetBufferStoreCtl(V, cpuRxExceptionEn0_f, &buffer_store_ctl, ((enable == TRUE)? 1 : 0));
            SetBufferStoreCtl(V, cpuRxExceptionEn1_f, &buffer_store_ctl, ((enable == TRUE)? 1 : 0));
        }
        if ((dir == CTC_EGRESS) || (dir == CTC_BOTH_DIRECTION))
        {
            SetBufferStoreCtl(V, cpuTxExceptionEn_f, &buffer_store_ctl, ((enable == TRUE)? 1 : 0));
        }

        cmd = DRV_IOW(BufferStoreCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &buffer_store_ctl),ret,exit);

        sal_memset(&ipe_cpurxtxexception_ctl, 0, sizeof(IpeCpuRxTxExceptionCtl_m));
        cmd = DRV_IOR(IpeCpuRxTxExceptionCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ipe_cpurxtxexception_ctl),ret,exit);

        if ((dir == CTC_INGRESS) || (dir == CTC_BOTH_DIRECTION))
        {
            SetIpeCpuRxTxExceptionCtl(V, cpuRxExceptionEn0_f, &ipe_cpurxtxexception_ctl, ((enable == TRUE)? 1 : 0));
            SetIpeCpuRxTxExceptionCtl(V, cpuRxExceptionEn1_f, &ipe_cpurxtxexception_ctl, ((enable == TRUE)? 1 : 0));
        }
        if ((dir == CTC_EGRESS) || (dir == CTC_BOTH_DIRECTION))
        {
            SetIpeCpuRxTxExceptionCtl(V, cpuTxExceptionEn_f, &ipe_cpurxtxexception_ctl, ((enable == TRUE)? 1 : 0));
        }

        cmd = DRV_IOW(IpeCpuRxTxExceptionCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ipe_cpurxtxexception_ctl),ret,exit);
        ret = CTC_E_NONE;
        goto exit;
    }
    MIRROR_UNLOCK;
    SYS_MAP_CTC_GPORT_TO_DRV_LPORT_WITH_CHECK(gport, lchip, lport);

    if (TRUE == enable)
    {
        SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "gport = 0x%X, direction = %d, span_id = %d\n", gport, dir, session_id);

        if (session_id >= MAX_CTC_MIRROR_SESSION_ID)
        {
            return CTC_E_INVALID_PARAM;
        }

        CTC_ERROR_RETURN(sys_usw_port_api_set_internal_direction_property(lchip, gport, SYS_PORT_DIR_PROP_L2_SPAN_ID, dir, session_id));
        CTC_ERROR_RETURN(sys_usw_port_api_set_internal_direction_property(lchip, gport, SYS_PORT_DIR_PROP_L2_SPAN_EN, dir, TRUE));
    }
    else if (FALSE == enable)
    {
        SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "gport = 0x%X, direction = %d\n", gport, dir);

        CTC_ERROR_RETURN(sys_usw_port_api_set_internal_direction_property(lchip, gport, SYS_PORT_DIR_PROP_L2_SPAN_EN, dir, FALSE));
    }
    return CTC_E_NONE;
exit:
    MIRROR_UNLOCK;
    return ret;
}

/*
 @brief This function is to get the information of port mirror
*/
int32
sys_usw_mirror_get_port_info(uint8 lchip, uint32 gport, ctc_direction_t dir, bool* enable, uint8* session_id)
{
    uint32 value = 0;
    uint32 value_enable = 0;

    SYS_MIRROR_INIT_CHECK();

    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "gport = %d, direction = %d\n", gport, dir);

    CTC_PTR_VALID_CHECK(enable);
    CTC_PTR_VALID_CHECK(session_id);

    CTC_ERROR_RETURN(sys_usw_port_api_get_internal_direction_property(lchip, gport, SYS_PORT_DIR_PROP_L2_SPAN_EN, dir, &value_enable));
    CTC_ERROR_RETURN(sys_usw_port_api_get_internal_direction_property(lchip, gport, SYS_PORT_DIR_PROP_L2_SPAN_ID, dir, &value));
    *session_id = value;
    *enable = value_enable ? TRUE : FALSE;

    return CTC_E_NONE;
}

/*
 @brief This function is to set vlan able to mirror
*/
int32
sys_usw_mirror_set_vlan_en(uint8 lchip, uint16 vlan_id, ctc_direction_t dir, bool enable, uint8 session_id)
{

    int32 ret = 0;

    SYS_MIRROR_INIT_CHECK();

    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    if (TRUE == enable)
    {
        SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "vlan_id = %d, direction = %d, span_id = %d\n", vlan_id, dir, session_id);

        CTC_VLAN_RANGE_CHECK(vlan_id);

        if (session_id >= MAX_CTC_MIRROR_SESSION_ID)
        {
            return CTC_E_INVALID_PARAM;
        }

        if ((dir == CTC_INGRESS) || (dir == CTC_BOTH_DIRECTION))
        {
            ret =  sys_usw_vlan_set_internal_property(lchip, vlan_id, SYS_VLAN_PROP_INGRESS_VLAN_SPAN_ID, session_id);
            ret = ret ? ret : sys_usw_vlan_set_internal_property(lchip, vlan_id, SYS_VLAN_PROP_INGRESS_VLAN_SPAN_EN, 1);
        }

        if ((dir == CTC_EGRESS) || (dir == CTC_BOTH_DIRECTION))
        {
            ret = ret ? ret : sys_usw_vlan_set_internal_property(lchip, vlan_id, SYS_VLAN_PROP_EGRESS_VLAN_SPAN_ID, session_id);
            ret = ret ? ret : sys_usw_vlan_set_internal_property(lchip, vlan_id, SYS_VLAN_PROP_EGRESS_VLAN_SPAN_EN, 1);
        }
    }
    else if (FALSE == enable)
    {
        SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "vlan_id = %d, direction = %d\n", vlan_id, dir);

        CTC_VLAN_RANGE_CHECK(vlan_id);

        if ((dir == CTC_INGRESS) || (dir == CTC_BOTH_DIRECTION))
        {
            CTC_ERROR_DUMP(sys_usw_vlan_set_internal_property(lchip, vlan_id, SYS_VLAN_PROP_INGRESS_VLAN_SPAN_EN, 0));
        }

        if ((dir == CTC_EGRESS) || (dir == CTC_BOTH_DIRECTION))
        {
            CTC_ERROR_DUMP(sys_usw_vlan_set_internal_property(lchip, vlan_id, SYS_VLAN_PROP_EGRESS_VLAN_SPAN_EN, 0));
        }
    }

    return ret;

}

/*
 @brief This function is to get the information of vlan mirror
*/
int32
sys_usw_mirror_get_vlan_info(uint8 lchip, uint16 vlan_id, ctc_direction_t dir, bool* enable, uint8* session_id)
{
    int32           ret = 0;
    uint32          value = 0;

    SYS_MIRROR_INIT_CHECK();

    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "vlan_id = %d, direction = %d\n", vlan_id, dir);

    CTC_VLAN_RANGE_CHECK(vlan_id);
    CTC_PTR_VALID_CHECK(enable);
    CTC_PTR_VALID_CHECK(session_id);
    MIRROR_LOCK;
    if (dir == CTC_INGRESS)
    {
        ret =  sys_usw_vlan_get_internal_property(lchip, vlan_id, SYS_VLAN_PROP_INGRESS_VLAN_SPAN_ID, &value);
        *session_id = value;
        ret = ret ? ret : sys_usw_vlan_get_internal_property(lchip, vlan_id, SYS_VLAN_PROP_INGRESS_VLAN_SPAN_EN, &value);
        *enable = value;
    }
    else if (dir == CTC_EGRESS)
    {
        ret =  sys_usw_vlan_get_internal_property(lchip, vlan_id, SYS_VLAN_PROP_EGRESS_VLAN_SPAN_ID, &value);
        *session_id = value;
        ret = ret ? ret : sys_usw_vlan_get_internal_property(lchip, vlan_id, SYS_VLAN_PROP_EGRESS_VLAN_SPAN_EN, &value);
        *enable = value;
    }
    else
    {
        ret = CTC_E_INVALID_PARAM;
        goto exit;
    }
exit:
    MIRROR_UNLOCK;
    return ret;

}
int32
sys_usw_mirror_mapping_excp_index(uint8 lchip, ctc_mirror_dest_t* mirror, uint32* p_out_idx, uint8 pos)
{
    uint32 excp_index = 0;
    if (mirror->type == CTC_MIRROR_L2SPAN_SESSION)    /*port mirror*/
    {
        if (CTC_INGRESS == mirror->dir)
        {
            excp_index = MCHIP_CAP(SYS_CAP_MIRROR_INGRESS_L2_SPAN_INDEX_BASE) + mirror->session_id;
        }
        else if (CTC_EGRESS == mirror->dir)
        {
            excp_index = MCHIP_CAP(SYS_CAP_MIRROR_EGRESS_L2_SPAN_INDEX_BASE) + mirror->session_id;
        }

    }
    else if (mirror->type == CTC_MIRROR_L3SPAN_SESSION)   /*vlan mirror*/
    {
        if (CTC_INGRESS == mirror->dir)
        {
            excp_index = MCHIP_CAP(SYS_CAP_MIRROR_INGRESS_L3_SPAN_INDEX_BASE) + mirror->session_id;
        }
        else if (CTC_EGRESS == mirror->dir)
        {
            excp_index = MCHIP_CAP(SYS_CAP_MIRROR_EGRESS_L3_SPAN_INDEX_BASE) + mirror->session_id;
        }
    }
    else if (mirror->type == CTC_MIRROR_ACLLOG_SESSION)  /*acllog0 mirror set dest*/
    {
        excp_index = SYS_MIRROR_ACL_LOG_EXCEPTION_IDX(mirror->dir, mirror->session_id, mirror->acl_priority);
    }
    else if (mirror->type == CTC_MIRROR_CPU_SESSION)
    {
        CTC_MAX_VALUE_CHECK(mirror->session_id,0);

        if (CTC_INGRESS == mirror->dir)
        {
            excp_index = MCHIP_CAP(SYS_CAP_MIRROR_CPU_RX_SPAN_INDEX);
        }
        else if (CTC_EGRESS == mirror->dir)
        {
            excp_index = MCHIP_CAP(SYS_CAP_MIRROR_CPU_TX_SPAN_INDEX);
        }

    }
    else if(mirror->type == CTC_MIRROR_IPFIX_LOG_SESSION)
    {
        CTC_MAX_VALUE_CHECK(mirror->session_id,0);

        if (CTC_INGRESS == mirror->dir)
        {
            excp_index = MCHIP_CAP(SYS_CAP_MIRROR_INGRESS_IPFIX_LOG_INDEX);
        }
        else if (CTC_EGRESS == mirror->dir)
        {
            excp_index = MCHIP_CAP(SYS_CAP_MIRROR_EGRESS_IPFIX_LOG_INDEX);
        }
    }
    if (DRV_FROM_AT(lchip))
    {
        *p_out_idx = (excp_index << 3) + pos;
    }
    else
    {
        *p_out_idx = excp_index;
    }
    return 0;
}
STATIC int32
_sys_usw_mirror_set_excp_index_and_dest_and_nhptr(uint8 lchip, ctc_mirror_dest_t* mirror, uint32 dest_gport, uint32 nh_ptr, uint8 pos)
{
    uint32 excp_index = 0;

    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "direction = %d, dest_gport = %d, session_id = %d, nh_ptr = %d\n", mirror->dir, dest_gport, mirror->session_id, nh_ptr);

    CTC_MAX_VALUE_CHECK(mirror->dir, CTC_EGRESS);
    CTC_MAX_VALUE_CHECK(mirror->session_id, MAX_CTC_MIRROR_SESSION_ID - 1);

    CTC_ERROR_RETURN(sys_usw_mirror_mapping_excp_index(lchip, mirror, &excp_index, pos));
    CTC_ERROR_RETURN(_sys_usw_mirror_set_dest_write_chip(lchip, excp_index, dest_gport, nh_ptr, mirror));

    return CTC_E_NONE;
}

/*
 @brief This function is to set remote mirror destination port
*/
STATIC int32
_sys_usw_mirror_rspan_set_dest(uint8 lchip, ctc_mirror_dest_t* mirror, uint32* nh_id, uint32* loop_gport, uint8 pos)
{
    uint32 nh_id_tmp = CTC_MAX_UINT32_VALUE;
    uint32 dsnh_offset = 0;
    uint32 temp_gport = 0;
    ctc_rspan_nexthop_param_t  temp_p_nh_param;

    sal_memset(&temp_p_nh_param, 0, sizeof(ctc_rspan_nexthop_param_t));

    SYS_MIRROR_INIT_CHECK();
    CTC_PTR_VALID_CHECK(mirror);

    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "dest_gport = %d, direction = %d, session_id = %d\n",
                       mirror->dest_gport, mirror->dir, mirror->session_id);

    SYS_GLOBAL_PORT_CHECK(mirror->dest_gport);

    if (0 != mirror->vlan_valid)
    {
        if (!sys_usw_chip_is_local(lchip, CTC_MAP_GPORT_TO_GCHIP(mirror->dest_gport)) && !CTC_IS_LINKAGG_PORT(mirror->dest_gport))
        {
            temp_p_nh_param.remote_chip = TRUE;
        }

        temp_p_nh_param.rspan_vid = mirror->rspan.vlan_id;
        CTC_ERROR_RETURN(sys_usw_rspan_nh_create(lchip, &nh_id_tmp, 0, &temp_p_nh_param));
    }
    else
    {
        nh_id_tmp = mirror->rspan.nh_id;
    }

    CTC_ERROR_RETURN(sys_usw_nh_get_mirror_info_by_nhid(lchip, nh_id_tmp, &dsnh_offset, &temp_gport, TRUE));

    if (temp_gport == CTC_MAX_UINT16_VALUE)
    {
        temp_gport = mirror->dest_gport;
    }
    /*for iloop nh or mcast nh*/
    CTC_ERROR_RETURN(_sys_usw_mirror_set_loop_port(lchip, nh_id_tmp, &temp_gport, mirror, pos));

    CTC_ERROR_RETURN(_sys_usw_mirror_set_excp_index_and_dest_and_nhptr(lchip, mirror, temp_gport, dsnh_offset, pos));

    *nh_id = nh_id_tmp;
    *loop_gport = temp_gport;

    return CTC_E_NONE;
}

int32
_sys_usw_mirror_param_check(uint8 lchip, ctc_mirror_dest_t* p_mirror)
{
    uint8 service_queue_egress_en = 0;
    uint32 dsnh_offset = 0;
    uint32 temp_gport = 0;
    uint8 pos = 0;

    /*remote cpu and tmm1.0 and tmm1.1 local cpu not support truncation*/
    if(p_mirror->truncated_len && CTC_IS_CPU_PORT(p_mirror->dest_gport) &&
        (!sys_usw_chip_is_local(lchip, CTC_MAP_GPORT_TO_GCHIP(p_mirror->dest_gport)) ||(DRV_IS_TMM(lchip) && (SYS_CHIP_SUB_VERSION_C != SYS_GET_CHIP_VERSION))))
    {
        return CTC_E_NOT_SUPPORT;
    }

    /* truncation length check */
    if (CTC_IS_BIT_SET(p_mirror->truncated_len, (sizeof(p_mirror->truncated_len)*CTC_UINT8_BITS - 1)))
    {
        CTC_MAX_VALUE_CHECK(p_mirror->truncated_len & ~(1<<(sizeof(p_mirror->truncated_len)*CTC_UINT8_BITS - 1)), SYS_TRUNCATION_PROFILE_MAX - 1);
    }
    else
    {
        CTC_MAX_VALUE_CHECK(p_mirror->truncated_len, (!DRV_FROM_TMM(lchip) && CTC_IS_CPU_PORT(p_mirror->dest_gport)) ? SYS_REASON_MAX_TRUNCATED_LEN : MCHIP_CAP(SYS_CAP_PKT_TRUNCATED_LEN));
    }
    SYS_GLOBAL_PORT_CHECK(p_mirror->dest_gport);
    CTC_ERROR_RETURN(sys_usw_global_get_logic_destport_en(lchip,&service_queue_egress_en));
    if(service_queue_egress_en && p_mirror->truncated_len)
    {
        return CTC_E_NOT_SUPPORT;
    }

    /* type and session check */
    if ((p_mirror->type >= MAX_CTC_MIRROR_SESSION_TYPE) || (p_mirror->session_id >= MAX_CTC_MIRROR_SESSION_ID)
        || (p_mirror->dir > CTC_BOTH_DIRECTION))
    {
        return CTC_E_INVALID_PARAM;
    }

    /* flow mirror acl priority check */
    if (p_mirror->type == CTC_MIRROR_ACLLOG_SESSION)
    {
        if (p_mirror->acl_priority >= SYS_MIRROR_ACLLOG_INGRESS_PRI_NUM)
        {
            return CTC_E_INVALID_PARAM;
        }
        if (( p_mirror->acl_priority >= SYS_MIRROR_ACLLOG_EGRESS_PRI_NUM) && ((CTC_BOTH_DIRECTION == p_mirror->dir) || (CTC_EGRESS == p_mirror->dir)))
        {
            return CTC_E_INVALID_PARAM;
        }
    }

    /* not support 1:N mirror before AT */
    if (!DRV_FROM_AT(lchip) && 0!=p_mirror->nh_cnt)
    {
        return CTC_E_INVALID_PARAM;
    }

    /* nh_array is null */
    if (p_mirror->nh_cnt && !p_mirror->nh_array)
    {
        return CTC_E_INVALID_PARAM;
    }

    /* set vlan_valid or nh_id, but not set is_rspan */
    if ((!p_mirror->is_rspan) && ((p_mirror->vlan_valid) || 0 != p_mirror->rspan.nh_id))
    {
        return CTC_E_INVALID_PARAM;
    }
    
    /* set vlan_valid and nh_id at same time */
    if (p_mirror->vlan_valid)
    {
        CTC_VLAN_RANGE_CHECK(p_mirror->rspan.vlan_id);
    }
    if (0 == p_mirror->nh_cnt)
    {
        if (0 == p_mirror->vlan_valid && p_mirror->is_rspan)
        {
            CTC_ERROR_RETURN(sys_usw_nh_get_mirror_info_by_nhid(lchip, p_mirror->rspan.nh_id, &dsnh_offset, &temp_gport, TRUE));
        }
    }
    else
    {
        for (pos = 0; pos < p_mirror->nh_cnt; pos++)
        {
            CTC_ERROR_RETURN(sys_usw_nh_get_mirror_info_by_nhid(lchip, p_mirror->nh_array[pos], &dsnh_offset, &temp_gport, TRUE));
        }
    }
    return CTC_E_NONE;
}

int32
_sys_usw_mirror_update_db(uint8 lchip, ctc_mirror_dest_t* p_mirror, uint32 nh_id, uint32 dest_gport, uint8 pos, uint8 is_add)
{
    sys_mirror_dest_node_t* dest_node = NULL;
    sys_mirror_dest_node_t* p_dest_node = NULL;
    sys_nh_info_dsnh_t nhinfo;
    uint8 type = 0;
    int32 ret = CTC_E_NONE;
    sys_mirror_dest_node_t node_tmp;
    
    sal_memset(&node_tmp, 0, sizeof(sys_mirror_dest_node_t));

    sys_usw_mirror_type_mapping(p_mirror->type, p_mirror->acl_priority, &type);
    node_tmp.type = type;
    node_tmp.session_id = p_mirror->session_id;
    node_tmp.dir = p_mirror->dir;
    node_tmp.member_index = pos;

    /* remove old db */
    p_dest_node = ctc_hash_remove(p_usw_mirror_master[lchip]->dest_hash, &node_tmp);
    if(p_dest_node)
    {
        mem_free(p_dest_node);
    }

    if (!is_add)
    {
        goto exit;
    }

    sal_memset(&nhinfo, 0, sizeof(nhinfo));
    if (p_mirror->is_rspan)
    {
        CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo(lchip, nh_id, &nhinfo, 0));
    }
    /* no need add new db */
    if ((!p_mirror->is_rspan && !CTC_IS_LINKAGG_PORT(dest_gport))
        || (p_mirror->is_rspan && !_sys_usw_mirror_check_alloced_nexthop(lchip, nh_id)
        && (DRV_FROM_TMM(lchip) || SYS_NH_TYPE_MCAST != nhinfo.nh_entry_type)
        && (SYS_NH_TYPE_ILOOP != nhinfo.nh_entry_type)
        && !CTC_IS_LINKAGG_PORT(dest_gport)))
    {
        goto exit;
    }

    /* TM and AT don't need to add new db in this case */
    if (CTC_IS_LINKAGG_PORT(dest_gport) && !p_mirror->vlan_valid && (DRV_IS_TSINGMA(lchip) || DRV_IS_AT(lchip)))
    {
        goto exit;
    }

    /* add new db */
    dest_node = mem_malloc(MEM_MIRROR_MODULE, sizeof(sys_mirror_dest_node_t));
    if (NULL == dest_node)
    {
        ret = CTC_E_NO_MEMORY;
        goto exit;
    }
    sal_memset(dest_node, 0, sizeof(sys_mirror_dest_node_t));

    dest_node->session_id = p_mirror->session_id;
    dest_node->type = type;
    dest_node->dir = p_mirror->dir;
    dest_node->member_index = pos;

    if (CTC_IS_LINKAGG_PORT(dest_gport) && p_mirror->vlan_valid)
    {
        dest_node->data_type = SYS_MIRROR_RSPAN_OVER_LINKAGG;
        dest_node->nh_id = nh_id;
        dest_node->linkagg_id = CTC_GPORT_LINKAGG_ID(dest_gport);
    }
    else if(CTC_IS_LINKAGG_PORT(dest_gport))
    {
        dest_node->data_type = SYS_MIRROR_SPAN_OVER_LINKAGG;
        dest_node->linkagg_id = CTC_GPORT_LINKAGG_ID(dest_gport);
    }
    else if(p_mirror->vlan_valid)
    {
        dest_node->data_type = SYS_MIRROR_RSPAN_OVER_VLAN;
        dest_node->nh_id = nh_id;
    }
    else if(p_mirror->is_rspan && SYS_NH_TYPE_MCAST == nhinfo.nh_entry_type)
    {
        dest_node->data_type = SYS_MIRROR_RSPAN_OVER_MCAST;
        dest_node->nh_id = nh_id;
        dest_node->loop_port = CTC_MAP_GPORT_TO_LPORT(dest_gport);
    }
    else if(p_mirror->is_rspan && SYS_NH_TYPE_ILOOP == nhinfo.nh_entry_type)
    {
        dest_node->data_type = SYS_MIRROR_RSPAN_OVER_ILOOP;
        dest_node->nh_id = nh_id;
        dest_node->loop_port = CTC_MAP_GPORT_TO_LPORT(dest_gport);
    }
    else
    {
        mem_free(dest_node);
        ret = CTC_E_INVALID_PARAM;
        goto exit;
    }

    /* add to hash by key */
    if (NULL == ctc_hash_insert(p_usw_mirror_master[lchip]->dest_hash, dest_node))
    {
        mem_free(dest_node);
        SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [MIRROR] Hash insert fail\n");
        ret= CTC_E_NO_MEMORY;
        goto exit;
    }

exit:
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_MIRROR, SYS_WB_APPID_MIRROR_SUBID_DEST, 1);
    return ret;
}

int32
_sys_usw_mirror_set_dest(uint8 lchip, ctc_mirror_dest_t* p_mirror, uint8 pos)
{
    int32 ret = CTC_E_NONE;
    uint32 nh_ptr = 0;
    uint32 nh_id = 0;
    uint32 temp_gport = 0;
    ctc_direction_t dir_tmp = 0;
    SYS_MIRROR_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_mirror);

    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "dest_gport = %d, direction = %d, session_id = %d\n",
                       p_mirror->dest_gport, p_mirror->dir, p_mirror->session_id);

    /* add new mirror session */
    dir_tmp = p_mirror->dir;
    if (p_mirror->is_rspan)
    {
        /* for rspan over vlan and rspan over nexthop */
        if (dir_tmp == CTC_INGRESS || dir_tmp == CTC_BOTH_DIRECTION)
        {
            p_mirror->dir = CTC_INGRESS;
            CTC_ERROR_GOTO(_sys_usw_mirror_unset_loop_port(lchip, p_mirror, pos), ret, exit);
            CTC_ERROR_GOTO(_sys_usw_mirror_rspan_set_dest(lchip, p_mirror, &nh_id, &temp_gport, pos), ret, exit);
            CTC_ERROR_GOTO(_sys_usw_mirror_update_db(lchip, p_mirror, nh_id, temp_gport, pos, 1), ret, exit);
        }
        if (dir_tmp == CTC_EGRESS || dir_tmp == CTC_BOTH_DIRECTION)
        {
            p_mirror->dir = CTC_EGRESS;
            CTC_ERROR_GOTO(_sys_usw_mirror_unset_loop_port(lchip, p_mirror, pos), ret, exit);
            CTC_ERROR_GOTO(_sys_usw_mirror_rspan_set_dest(lchip, p_mirror, &nh_id, &temp_gport, pos), ret, exit);
            CTC_ERROR_GOTO(_sys_usw_mirror_update_db(lchip, p_mirror, nh_id, temp_gport, pos, 1), ret, exit);
        }
    }
    else
    {
        /* local span (include to linkagg and to cpu) */
        CTC_ERROR_GOTO(sys_usw_nh_get_resolved_offset(lchip, SYS_NH_RES_OFFSET_TYPE_MIRROR_NH, &nh_ptr), ret, exit);

        if (dir_tmp == CTC_INGRESS || dir_tmp == CTC_BOTH_DIRECTION)
        {
            p_mirror->dir = CTC_INGRESS;
            CTC_ERROR_GOTO(_sys_usw_mirror_unset_loop_port(lchip, p_mirror, pos), ret, exit);
            CTC_ERROR_GOTO(_sys_usw_mirror_set_excp_index_and_dest_and_nhptr(lchip, p_mirror, p_mirror->dest_gport, nh_ptr, pos), ret, exit);
            CTC_ERROR_GOTO(_sys_usw_mirror_update_db(lchip, p_mirror, nh_id, p_mirror->dest_gport, pos, 1), ret, exit);
        }
        if (dir_tmp == CTC_EGRESS || dir_tmp == CTC_BOTH_DIRECTION)
        {
            p_mirror->dir = CTC_EGRESS;
            CTC_ERROR_GOTO(_sys_usw_mirror_unset_loop_port(lchip, p_mirror, pos), ret, exit);
            CTC_ERROR_GOTO(_sys_usw_mirror_set_excp_index_and_dest_and_nhptr(lchip, p_mirror, p_mirror->dest_gport, nh_ptr, pos), ret, exit);
            CTC_ERROR_GOTO(_sys_usw_mirror_update_db(lchip, p_mirror, nh_id, p_mirror->dest_gport, pos, 1), ret, exit);
        }
    }

exit:
    p_mirror->dir = dir_tmp;
    return ret;
}

int32
_sys_usw_mirror_unset_dest(uint8 lchip, ctc_mirror_dest_t* p_mirror, uint8 pos)
{
    uint8 gchip = 0;
    uint32 nh_ptr = 0;
    ctc_direction_t dir_tmp = 0;

    SYS_MIRROR_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_mirror);

    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "session_id = %d, direction = %d, session type = %d\n",
                       p_mirror->session_id, p_mirror->dir, p_mirror->type);

    /* 1. set dest to drop */
    sys_usw_get_gchip_id(lchip, &gchip);
    p_mirror->dest_gport = CTC_MAP_LPORT_TO_GPORT(gchip, SYS_RSV_PORT_DROP_ID);

    /* 2. get nh_ptr */
    CTC_ERROR_RETURN(sys_usw_nh_get_resolved_offset(lchip, SYS_NH_RES_OFFSET_TYPE_MIRROR_NH, &nh_ptr));

    /* 3. update hw and db */
    dir_tmp = p_mirror->dir;
    if (dir_tmp == CTC_INGRESS || dir_tmp == CTC_BOTH_DIRECTION)
    {
        p_mirror->dir = CTC_INGRESS;
        CTC_ERROR_RETURN(_sys_usw_mirror_unset_loop_port(lchip, p_mirror, pos));
        CTC_ERROR_RETURN(_sys_usw_mirror_set_excp_index_and_dest_and_nhptr(lchip, p_mirror, p_mirror->dest_gport, nh_ptr, pos));
        CTC_ERROR_RETURN(_sys_usw_mirror_update_db(lchip, p_mirror, 0, 0, pos, 0));
    }
    if (dir_tmp == CTC_EGRESS || dir_tmp == CTC_BOTH_DIRECTION)
    {
        p_mirror->dir = CTC_EGRESS;
        CTC_ERROR_RETURN(_sys_usw_mirror_unset_loop_port(lchip, p_mirror, pos));
        CTC_ERROR_RETURN(_sys_usw_mirror_set_excp_index_and_dest_and_nhptr(lchip, p_mirror, p_mirror->dest_gport, nh_ptr, pos));
        CTC_ERROR_RETURN(_sys_usw_mirror_update_db(lchip, p_mirror, 0, 0, pos, 0));
    }
    p_mirror->dir = dir_tmp;

    return CTC_E_NONE;
}

int32
sys_usw_mirror_rspan_escape_en(uint8 lchip, bool enable)
{
    uint32 cmd;
    uint32 field_val;
    int32  ret  = CTC_E_NONE;
    SYS_MIRROR_INIT_CHECK();

    field_val = (TRUE == enable) ? 1 : 0;

    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    MIRROR_LOCK;
    cmd = DRV_IOW(EpePktProcCtl_t, EpePktProcCtl_mirrorEscapeCamEn_f);
    CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val),ret,exit);
exit:
    MIRROR_UNLOCK;
    return ret;
}

int32
sys_usw_mirror_rspan_escape_mac(uint8 lchip, ctc_mirror_rspan_escape_t* p_escape)
{
    uint32 cmd = 0;
    int32  ret  = CTC_E_NONE;
    hw_mac_addr_t mac_addr = {0};
    EpeMirrorEscapeCam_m mirror_escape;

    SYS_MIRROR_INIT_CHECK();

    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    sal_memset(&mirror_escape, 0,sizeof(mirror_escape));

    MIRROR_LOCK;
    MIRROR_SET_HW_MAC(mac_addr, p_escape->mac0);
    SetEpeMirrorEscapeCam(A, array_0_macDaValue_f, &mirror_escape, &mac_addr);
    MIRROR_SET_HW_MAC(mac_addr, p_escape->mac_mask0);
    SetEpeMirrorEscapeCam(A, array_0_macDaMask_f, &mirror_escape, &mac_addr);

    MIRROR_SET_HW_MAC(mac_addr, p_escape->mac1);
    SetEpeMirrorEscapeCam(A, array_1_macDaValue_f, &mirror_escape, &mac_addr);
    MIRROR_SET_HW_MAC(mac_addr, p_escape->mac_mask1);
    SetEpeMirrorEscapeCam(A, array_1_macDaMask_f, &mirror_escape, &mac_addr);

    SetEpeMirrorEscapeCam(V, array_0_valid_f, &mirror_escape, 1);
    SetEpeMirrorEscapeCam(V, array_1_valid_f, &mirror_escape, 1);

    cmd = DRV_IOW(EpeMirrorEscapeCam_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &mirror_escape),ret,exit);
exit:
    MIRROR_UNLOCK;
    return ret;
}

/*
 @brief This function is to set local mirror destination members
*/
int32
sys_usw_mirror_set_dests(uint8 lchip, ctc_mirror_dest_t* p_mirror)
{
    int32 ret = CTC_E_NONE;
    uint8 pos = 0;
    ctc_mirror_dest_t mirror;
    uint8 member_bmp = 0;
    uint8 dir_tmp = 0;

    SYS_MIRROR_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_mirror);

    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "dest_gport = %d, direction = %d, session_id = %d\n",
                       p_mirror->dest_gport, p_mirror->dir, p_mirror->session_id);

    if (p_mirror->nh_cnt > MCHIP_CAP(SYS_CAP_MIRROR_MEMBER_NUM))
    {
        return CTC_E_INVALID_PARAM;
    }

    /* 1. param check */
    CTC_ERROR_RETURN(_sys_usw_mirror_param_check(lchip, p_mirror));

    MIRROR_LOCK;
    sal_memcpy(&mirror, p_mirror, sizeof(mirror));

    /* 2. set destination */
    if (0 == mirror.nh_cnt)
    {
        /* 1:1 mirrror & 1:N mirror（mcast）*/
        CTC_ERROR_GOTO(_sys_usw_mirror_set_dest(lchip, &mirror, pos++), ret, exit);
        CTC_BIT_SET(member_bmp, 0);
    }
    else
    {
        /* 1:N mirror, from AT, support 8 dests (not mcast mode)*/
        mirror.is_rspan = 1;
        mirror.vlan_valid = 0;
        for (pos=0;pos<mirror.nh_cnt;pos++)
        {
            mirror.rspan.nh_id = mirror.nh_array[pos];
            CTC_ERROR_GOTO(_sys_usw_mirror_set_dest(lchip, &mirror, pos), ret, exit);
            CTC_BIT_SET(member_bmp, pos);
        }
        pos = mirror.nh_cnt;
    }
    
    /* unset the rest of member */
    for(; pos < MCHIP_CAP(SYS_CAP_MIRROR_MEMBER_NUM); pos++)
    {
         mirror.is_rspan = 0;
        _sys_usw_mirror_unset_dest(lchip, &mirror, pos);
    }

    /* 3. update DsMetFifoPreExcp from AT, indicate  */
    if (DRV_FROM_AT(lchip))
    {
        uint32 cmd = 0;
        uint32 excp_index = 0;
        DsMetFifoPreExcp_m met_pre_excp;

        dir_tmp = mirror.dir;
        sal_memset(&met_pre_excp, 0, sizeof(DsMetFifoPreExcp_m));

        if (CTC_INGRESS == dir_tmp || CTC_BOTH_DIRECTION == dir_tmp)
        {
            mirror.dir = CTC_INGRESS;
            CTC_ERROR_GOTO(sys_usw_mirror_mapping_excp_index(lchip, &mirror, &excp_index, 0), ret, exit);
            excp_index = excp_index / MCHIP_CAP(SYS_CAP_MIRROR_MEMBER_NUM);
            SetDsMetFifoPreExcp(V, replicationVector_f, &met_pre_excp, member_bmp);
            cmd = DRV_IOW(DsMetFifoPreExcp_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, excp_index, cmd, &met_pre_excp), ret, exit);
        }
        if (CTC_EGRESS == dir_tmp || CTC_BOTH_DIRECTION == dir_tmp)
        {
            mirror.dir = CTC_EGRESS;
            CTC_ERROR_GOTO(sys_usw_mirror_mapping_excp_index(lchip, &mirror, &excp_index, 0), ret, exit);
            excp_index = excp_index / MCHIP_CAP(SYS_CAP_MIRROR_MEMBER_NUM);
            SetDsMetFifoPreExcp(V, replicationVector_f, &met_pre_excp, member_bmp);
            cmd = DRV_IOW(DsMetFifoPreExcp_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, excp_index, cmd, &met_pre_excp), ret, exit);
        }
    }

exit:

    MIRROR_UNLOCK;
    return ret;
}

/*
 @brief This function is to remove mirror members
*/
int32
sys_usw_mirror_unset_dests(uint8 lchip, ctc_mirror_dest_t* p_mirror)
{
    int32 ret = CTC_E_NONE;
    uint8 pos = 0;
    uint8 dir_tmp = 0;
    ctc_mirror_dest_t mirror;
    uint32 excp_index = 0;
    DsMetFifoExcp_m met_excp;
    uint32 cmd;
    uint32 destmap = 0;
    uint8 gchip = 0;
    SYS_MIRROR_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_mirror);

    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    
    /* 1.check */
    CTC_ERROR_RETURN(_sys_usw_mirror_param_check(lchip, p_mirror));
    CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip));
    CTC_ERROR_RETURN(sys_usw_mirror_mapping_excp_index(lchip, p_mirror, &excp_index, 0));
    cmd = DRV_IOR(DsMetFifoExcp_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd, &met_excp));
    destmap = GetDsMetFifoExcp(V, destMap_f, &met_excp);
    if (destmap == SYS_ENCODE_DESTMAP(gchip, SYS_RSV_PORT_DROP_ID))
    {
        return CTC_E_INVALID_CONFIG;
    }
    
    MIRROR_LOCK;
    sal_memcpy(&mirror, p_mirror, sizeof(mirror));

    /* 2. remove all old dests, release internal nexthop and internal loop port, update linkagg ref_cnt */
    for (pos = 0; pos < MCHIP_CAP(SYS_CAP_MIRROR_MEMBER_NUM); pos++)
    {
        _sys_usw_mirror_unset_dest(lchip, &mirror, pos);
    }

    /* 3. update DsMetFifoPreExcp from AT */
    if (DRV_FROM_AT(lchip))
    {
        uint32 cmd = 0;
        uint32 excp_index = 0;
        DsMetFifoPreExcp_m met_pre_excp;

        dir_tmp = mirror.dir;
        sal_memset(&met_pre_excp, 0, sizeof(DsMetFifoPreExcp_m));

        if (CTC_INGRESS == dir_tmp || CTC_BOTH_DIRECTION == dir_tmp)
        {
            mirror.dir = CTC_INGRESS;
            CTC_ERROR_GOTO(sys_usw_mirror_mapping_excp_index(lchip, &mirror, &excp_index, 0), ret, exit);
            excp_index = excp_index / MCHIP_CAP(SYS_CAP_MIRROR_MEMBER_NUM);
            SetDsMetFifoPreExcp(V, replicationVector_f, &met_pre_excp, 0);
            cmd = DRV_IOW(DsMetFifoPreExcp_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, excp_index, cmd, &met_pre_excp), ret, exit);
        }
        if (CTC_EGRESS == dir_tmp || CTC_BOTH_DIRECTION == dir_tmp)
        {
            mirror.dir = CTC_EGRESS;
            CTC_ERROR_GOTO(sys_usw_mirror_mapping_excp_index(lchip, &mirror, &excp_index, 0), ret, exit);
            excp_index = excp_index / MCHIP_CAP(SYS_CAP_MIRROR_MEMBER_NUM);
            SetDsMetFifoPreExcp(V, replicationVector_f, &met_pre_excp, 0);
            cmd = DRV_IOW(DsMetFifoPreExcp_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, excp_index, cmd, &met_pre_excp), ret, exit);
        }
        mirror.dir = dir_tmp;
    }

exit:
    MIRROR_UNLOCK;
    return ret;
}

/*
  @brief This functions is used to set packet enable or not to log if the packet is discarded on EPE process.
*/
int32
sys_usw_mirror_set_mirror_discard(uint8 lchip, ctc_direction_t dir, uint16 discard_flag, bool enable)
{
    uint32 cmd;
    uint32 logon_discard;
    uint16 discard_flag_temp = 0;
    int32  ret  = CTC_E_NONE;
    SYS_MIRROR_INIT_CHECK();
    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "discard_flag = %d, direction = %d, enable = %d\n", discard_flag, dir, enable);
    SYS_MIRROR_DISCARD_CHECK(discard_flag);
    MIRROR_LOCK;

    if ((CTC_INGRESS == dir) || (CTC_BOTH_DIRECTION == dir))
    {
        if (discard_flag & CTC_MIRROR_L2SPAN_DISCARD)
        {
            CTC_SET_FLAG(discard_flag_temp, DRV_CONST(DRV_MIRROR_INGRESS_L2SPAN_DISCARD));
        }

        if (discard_flag & CTC_MIRROR_L3SPAN_DISCARD)
        {
            CTC_SET_FLAG(discard_flag_temp, DRV_CONST(DRV_MIRROR_INGRESS_L3SPAN_DISCARD));
        }

        if (discard_flag & CTC_MIRROR_ACLLOG_PRI_DISCARD)
        {
            CTC_SET_FLAG(discard_flag_temp, DRV_CONST(DRV_MIRROR_INGRESS_ACLLOG_PRI_DISCARD));
        }

        if (discard_flag & CTC_MIRROR_IPFIX_DISCARD)
        {
            CTC_SET_FLAG(discard_flag_temp, DRV_CONST(DRV_MIRROR_INGRESS_IPFIX_MIRROR_DISCARD));
        }

        cmd = DRV_IOR(IpeFwdCtl_t, IpeFwdCtl_logOnDiscard_f);
        CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &logon_discard),ret,exit);

        if (TRUE == enable)
        {
            CTC_SET_FLAG(logon_discard, discard_flag_temp);
        }
        else
        {
            CTC_UNSET_FLAG(logon_discard, discard_flag_temp);
        }

        cmd = DRV_IOW(IpeFwdCtl_t, IpeFwdCtl_logOnDiscard_f);
        CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &logon_discard),ret,exit);
        cmd = DRV_IOW(IpeAclQosCtl_t, IpeAclQosCtl_logOnDiscard_f);
        CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &logon_discard),ret,exit);
    }

    discard_flag_temp = 0;
    if ((CTC_EGRESS == dir) || (CTC_BOTH_DIRECTION == dir))
    {
        if (discard_flag & CTC_MIRROR_L2SPAN_DISCARD)
        {
            CTC_SET_FLAG(discard_flag_temp, DRV_CONST(DRV_MIRROR_EGRESS_L2SPAN_DISCARD));
        }

        if (discard_flag & CTC_MIRROR_L3SPAN_DISCARD)
        {
            CTC_SET_FLAG(discard_flag_temp, DRV_CONST(DRV_MIRROR_EGRESS_L3SPAN_DISCARD));
        }

        if (discard_flag & CTC_MIRROR_ACLLOG_PRI_DISCARD)
        {
            CTC_SET_FLAG(discard_flag_temp, DRV_CONST(DRV_MIRROR_EGRESS_ACLLOG_PRI_DISCARD));
        }

        if (discard_flag & CTC_MIRROR_IPFIX_DISCARD)
        {
            CTC_SET_FLAG(discard_flag_temp, DRV_ENUM(DRV_MIRROR_EGRESS_IPFIX_MIRROR_DISCARD));
        }

        cmd = DRV_IOR(EpeHeaderEditCtl_t, EpeHeaderEditCtl_logOnDiscard_f);
        CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &logon_discard),ret,exit);

        if (TRUE == enable)
        {
            CTC_SET_FLAG(logon_discard, discard_flag_temp);
        }
        else
        {
            CTC_UNSET_FLAG(logon_discard, discard_flag_temp);
        }

        cmd = DRV_IOW(EpeHeaderEditCtl_t, EpeHeaderEditCtl_logOnDiscard_f);
        CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &logon_discard),ret,exit);
    }
exit:
    MIRROR_UNLOCK;
    return ret;
}

int32
sys_usw_mirror_get_mirror_discard(uint8 lchip, ctc_direction_t dir, ctc_mirror_discard_t discard_flag, bool* p_enable)
{
    uint32 cmd = 0;
    uint32 field_val = 0;
    uint16 discard_flag_temp = 0;
    int32  ret  = CTC_E_NONE;
    SYS_MIRROR_INIT_CHECK();
    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "discard_flag = %d, direction = %d\n", discard_flag, dir);

    CTC_PTR_VALID_CHECK(p_enable);
    SYS_MIRROR_DISCARD_CHECK(discard_flag);

    switch (discard_flag)
    {
    case CTC_MIRROR_L2SPAN_DISCARD:
    case CTC_MIRROR_L3SPAN_DISCARD:
    case CTC_MIRROR_ACLLOG_PRI_DISCARD:
    case CTC_MIRROR_IPFIX_DISCARD:
        break;

    default:
        return CTC_E_INVALID_PARAM;
    }

    MIRROR_LOCK;
    switch (dir)
    {
    case CTC_INGRESS:

        if (discard_flag & CTC_MIRROR_L2SPAN_DISCARD)
        {
            CTC_SET_FLAG(discard_flag_temp, DRV_CONST(DRV_MIRROR_INGRESS_L2SPAN_DISCARD));
        }
        if (discard_flag & CTC_MIRROR_L3SPAN_DISCARD)
        {
            CTC_SET_FLAG(discard_flag_temp, DRV_CONST(DRV_MIRROR_INGRESS_L3SPAN_DISCARD));
        }
        if (discard_flag & CTC_MIRROR_ACLLOG_PRI_DISCARD)
        {
                CTC_SET_FLAG(discard_flag_temp, DRV_CONST(DRV_MIRROR_INGRESS_ACLLOG_PRI_DISCARD));
        }
        if (discard_flag & CTC_MIRROR_IPFIX_DISCARD)
        {
                CTC_SET_FLAG(discard_flag_temp, DRV_CONST(DRV_MIRROR_INGRESS_IPFIX_MIRROR_DISCARD));
        }

        cmd = DRV_IOR(IpeFwdCtl_t, IpeFwdCtl_logOnDiscard_f);
        break;

    case CTC_EGRESS:

        if (discard_flag & CTC_MIRROR_L2SPAN_DISCARD)
        {
            CTC_SET_FLAG(discard_flag_temp, DRV_CONST(DRV_MIRROR_EGRESS_L2SPAN_DISCARD));
        }
        if (discard_flag & CTC_MIRROR_L3SPAN_DISCARD)
        {
            CTC_SET_FLAG(discard_flag_temp, DRV_CONST(DRV_MIRROR_EGRESS_L3SPAN_DISCARD));
        }
        if (discard_flag & CTC_MIRROR_ACLLOG_PRI_DISCARD)
        {
            CTC_SET_FLAG(discard_flag_temp, DRV_CONST(DRV_MIRROR_EGRESS_ACLLOG_PRI_DISCARD));
        }
        if (discard_flag & CTC_MIRROR_IPFIX_DISCARD)
        {
            CTC_SET_FLAG(discard_flag_temp, DRV_ENUM(DRV_MIRROR_EGRESS_IPFIX_MIRROR_DISCARD));
        }


        cmd = DRV_IOR(EpeHeaderEditCtl_t, EpeHeaderEditCtl_logOnDiscard_f);
        break;

    default:
        ret = CTC_E_INVALID_PARAM;
        goto exit;
    }

    CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val),ret,exit);

    *p_enable = CTC_FLAG_ISSET(field_val, discard_flag_temp) ? TRUE : FALSE;
exit:
    MIRROR_UNLOCK;
    return ret;
}

int32
sys_usw_mirror_set_erspan_psc(uint8 lchip, ctc_mirror_erspan_psc_t* psc)
{
    uint32 value = 0;
    EpeNextHopCtl_m ctl;
    uint32 cmd = 0;
    int32  ret  = CTC_E_NONE;
    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_MIRROR_INIT_CHECK();
    CTC_PTR_VALID_CHECK(psc);
    MIRROR_LOCK;
    cmd = DRV_IOR(EpeNextHopCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd , &ctl),ret,exit);

    if(CTC_FLAG_ISSET(psc->type, CTC_MIRROR_ERSPAN_PSC_TYPE_IPV4))
    {
        value = CTC_FLAG_ISSET(psc->ipv4_flag, CTC_MIRROR_ERSPAN_PSC_IPV4_FLAG_L4_PORT);
        SetEpeNextHopCtl(V,symmetricalHashCtl_0_l4PortEn_f, &ctl, value);

        value = CTC_FLAG_ISSET(psc->ipv4_flag, CTC_MIRROR_ERSPAN_PSC_IPV4_FLAG_IP_ADDR);
        SetEpeNextHopCtl(V,symmetricalHashCtl_0_addrEn_f, &ctl, value);

        value = CTC_FLAG_ISSET(psc->ipv4_flag, CTC_MIRROR_ERSPAN_PSC_IPV4_FLAG_IS_TCP);
        SetEpeNextHopCtl(V,symmetricalHashCtl_0_tcpEn_f, &ctl, value);

        value = CTC_FLAG_ISSET(psc->ipv4_flag, CTC_MIRROR_ERSPAN_PSC_IPV4_FLAG_IS_UDP);
        SetEpeNextHopCtl(V,symmetricalHashCtl_0_udpEn_f, &ctl, value);

        value = CTC_FLAG_ISSET(psc->ipv4_flag, CTC_MIRROR_ERSPAN_PSC_IPV4_FLAG_IS_DCCP);
        SetEpeNextHopCtl(V,symmetricalHashCtl_0_dccpEn_f, &ctl, value);

        value = CTC_FLAG_ISSET(psc->ipv4_flag, CTC_MIRROR_ERSPAN_PSC_IPV4_FLAG_IS_SCTP);
        SetEpeNextHopCtl(V,symmetricalHashCtl_0_sctpEn_f, &ctl, value);
    }

    if(CTC_FLAG_ISSET(psc->type, CTC_MIRROR_ERSPAN_PSC_TYPE_IPV6))
    {
        value = CTC_FLAG_ISSET(psc->ipv6_flag, CTC_MIRROR_ERSPAN_PSC_IPV6_FLAG_L4_PORT);
        SetEpeNextHopCtl(V,symmetricalHashCtl_1_l4PortEn_f, &ctl, value);

        value = CTC_FLAG_ISSET(psc->ipv6_flag, CTC_MIRROR_ERSPAN_PSC_IPV6_FLAG_IP_ADDR);
        SetEpeNextHopCtl(V,symmetricalHashCtl_1_addrEn_f, &ctl, value);

        value = CTC_FLAG_ISSET(psc->ipv6_flag, CTC_MIRROR_ERSPAN_PSC_IPV6_FLAG_IS_TCP);
        SetEpeNextHopCtl(V,symmetricalHashCtl_1_tcpEn_f, &ctl, value);

        value = CTC_FLAG_ISSET(psc->ipv6_flag, CTC_MIRROR_ERSPAN_PSC_IPV6_FLAG_IS_UDP);
        SetEpeNextHopCtl(V,symmetricalHashCtl_1_udpEn_f, &ctl, value);

        value = CTC_FLAG_ISSET(psc->ipv6_flag, CTC_MIRROR_ERSPAN_PSC_IPV6_FLAG_IS_DCCP);
        SetEpeNextHopCtl(V,symmetricalHashCtl_1_dccpEn_f, &ctl, value);

        value = CTC_FLAG_ISSET(psc->ipv6_flag, CTC_MIRROR_ERSPAN_PSC_IPV6_FLAG_IS_SCTP);
        SetEpeNextHopCtl(V,symmetricalHashCtl_1_sctpEn_f, &ctl, value);
    }

    cmd = DRV_IOW(EpeNextHopCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ctl),ret,exit);
exit:
    MIRROR_UNLOCK;
    return ret;
}

STATIC int32
_sys_usw_mirror_show_dst_port(uint8 lchip,uint32 excp_index, uint32 session_id, uint8 ctc_type, ctc_direction_t dir, uint8 acl_prio)
{
    uint32 cmd = 0;
    uint32 dst_gport = 0;
    uint32 drv_gport = 0;
    DsMetFifoExcp_m met_excp;
    ds_t epehdr_adj_exp;
    uint32 value = 0;
    uint32 tbl_id = DRV_FROM_TMM(lchip)? EpeHdrAdjExcp_t: DsBufRetrvExcp_t;
    uint8  mem_num = MCHIP_CAP(SYS_CAP_MIRROR_MEMBER_NUM);
    uint8  bit_width = DRV_FROM_AT(lchip)? 3 : 0;
    uint8  cur_pos = 0;
    char*  string[4] = {"Port", "Vlan", "Acl", "CPU"};
    char*  desc[2] = {"Ingress", "Egress"};

    excp_index <<= bit_width;
    for (cur_pos = 0; cur_pos < mem_num; cur_pos++)
    {
        cmd = DRV_IOR(DsMetFifoExcp_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd, &met_excp));
        if ((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)) && GetDsMetFifoExcp(V, unionDestType_f, &met_excp))
        {
            ctc_mirror_dest_t mirror;
            sys_mirror_dest_node_t* dest_node = NULL;
            sal_memset(&mirror, 0, sizeof(ctc_mirror_dest_t));

            mirror.session_id = session_id;
            mirror.type = ctc_type;
            mirror.dir = dir;
            mirror.acl_priority = acl_prio;

            dest_node = _sys_usw_mirror_get_db_info(lchip, &mirror, cur_pos);
            dst_gport = CTC_MAP_TID_TO_GPORT(dest_node->linkagg_id);
        }
        else
        {
            GetDsMetFifoExcp(A, destMap_f, &met_excp, &value);
            if (SYS_DESTMAP_IS_CPU(value))
            {
                dst_gport = 0xffff;
            }
            else
            {
                drv_gport = SYS_USW_DESTMAP_TO_DRV_GPORT(value);
                dst_gport = SYS_MAP_DRV_GPORT_TO_CTC_GPORT(drv_gport);
            }
        }
        /*if mirror source is valid, print one dest at least*/
        if (SYS_IS_DROP_PORT(dst_gport) && cur_pos != 0)
        {
            break;
        }
        else if (SYS_IS_DROP_PORT(dst_gport) && 0 == cur_pos)
        {
            mem_num = 1;
        }
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index, cmd, &epehdr_adj_exp));
        GetEpeHdrAdjExcp(A, nextHopPtr_f, &epehdr_adj_exp, &value);

        if (CTC_MIRROR_ACLLOG_SESSION == ctc_type)
        {
            if (0xffff == dst_gport)
            {
                SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-5s %-10d %-10d %-10s %-10s 0x%-10.4x \n", string[ctc_type], session_id, acl_prio, desc[dir], "CPU", value);
            }
            else
            {
                SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-5s %-10d %-10d %-10s 0x%-8.4x 0x%-10.4x \n", string[ctc_type], session_id, acl_prio, desc[dir], dst_gport, value);
            }
        }
        else
        {
            if (0xffff == dst_gport)
            {
                SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-5s %-10d %-10s %-10s 0x%-10.4x \n", string[ctc_type], session_id, desc[dir], "CPU", value);
            }
            else
            {
                SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-5s %-10d %-10s 0x%-8.4x 0x%-10.4x \n", string[ctc_type], session_id, desc[dir], dst_gport, value);
            }
        }
        excp_index++;
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_mirror_show_port_info(uint8 lchip, uint32 gport)
{
    uint32 excp_index = 0;
    uint32 cmd = 0;
    uint32 session_id = 0;
    uint32 enable = FALSE;
    ctc_direction_t dir;
    DsMetFifoExcp_m met_excp;
    BufferStoreCtl_m buffer_store_ctl;
    IpeCpuRxTxExceptionCtl_m ipe_cpu_rxtx_exception_ctl;
    ds_t epehdr_adj_exp;

    sal_memset(&met_excp, 0, sizeof(DsMetFifoExcp_m));
    sal_memset(&epehdr_adj_exp, 0, sizeof(ds_t));

    SYS_MIRROR_INIT_CHECK();

    if (CTC_IS_CPU_PORT(gport))
    {
        dir = CTC_INGRESS;
        if (!DRV_FROM_TMM(lchip))
        {
            cmd = DRV_IOR(BufferStoreCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &buffer_store_ctl));
            GetBufferStoreCtl(A, cpuRxExceptionEn1_f, &buffer_store_ctl, &enable);
        }
        else
        {
            cmd = DRV_IOR(IpeCpuRxTxExceptionCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ipe_cpu_rxtx_exception_ctl));
            GetIpeCpuRxTxExceptionCtl(A, cpuRxExceptionEn1_f, &ipe_cpu_rxtx_exception_ctl, &enable);
        }

        excp_index = MCHIP_CAP(SYS_CAP_MIRROR_CPU_RX_SPAN_INDEX);

        SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "================================================== \n");
        SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-5s %-10s %-10s %-10s %-10s\n", "Type", "Session-ID", "Direction", "Dest-Port", "Nexthop-Ptr");
        SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-------------------------------------------------- \n");

        if (enable == TRUE)
        {
            _sys_usw_mirror_show_dst_port(lchip, excp_index, session_id, CTC_MIRROR_CPU_SESSION, CTC_INGRESS, 0);
        }

        enable = FALSE;
        dir = CTC_EGRESS;
        if (!DRV_FROM_TMM(lchip))
        {
            cmd = DRV_IOR(BufferStoreCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &buffer_store_ctl));
            GetBufferStoreCtl(A, cpuTxExceptionEn_f, &buffer_store_ctl, &enable);
        }
        else
        {
            cmd = DRV_IOR(IpeCpuRxTxExceptionCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ipe_cpu_rxtx_exception_ctl));
            GetIpeCpuRxTxExceptionCtl(A, cpuTxExceptionEn_f, &ipe_cpu_rxtx_exception_ctl, &enable);
        }

        excp_index = MCHIP_CAP(SYS_CAP_MIRROR_CPU_TX_SPAN_INDEX);

        if (enable == TRUE)
        {
            _sys_usw_mirror_show_dst_port(lchip, excp_index, session_id, CTC_MIRROR_CPU_SESSION, CTC_EGRESS, 0);
        }

        SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "================================================== \n");
        return CTC_E_NONE;
    }

    dir = CTC_INGRESS;
    CTC_ERROR_RETURN(sys_usw_port_api_get_internal_direction_property(lchip, gport, SYS_PORT_DIR_PROP_L2_SPAN_EN, dir, &enable));
    CTC_ERROR_RETURN(sys_usw_port_api_get_internal_direction_property(lchip, gport, SYS_PORT_DIR_PROP_L2_SPAN_ID, dir, &session_id));

    excp_index = MCHIP_CAP(SYS_CAP_MIRROR_INGRESS_L2_SPAN_INDEX_BASE) + session_id;

    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "================================================== \n");
    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-5s %-10s %-10s %-10s %-10s\n", "Type", "Session-ID", "Direction", "Dest-Port", "Nexthop-Ptr");
    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-------------------------------------------------- \n");

    if (enable == TRUE)
    {
        _sys_usw_mirror_show_dst_port(lchip, excp_index, session_id, CTC_MIRROR_L2SPAN_SESSION, CTC_INGRESS, 0);
    }

    enable = FALSE;
    dir = CTC_EGRESS;
    CTC_ERROR_RETURN(sys_usw_port_api_get_internal_direction_property(lchip, gport, SYS_PORT_DIR_PROP_L2_SPAN_EN, dir, &enable));
    CTC_ERROR_RETURN(sys_usw_port_api_get_internal_direction_property(lchip, gport, SYS_PORT_DIR_PROP_L2_SPAN_ID, dir, &session_id));

    excp_index = MCHIP_CAP(SYS_CAP_MIRROR_EGRESS_L2_SPAN_INDEX_BASE) + session_id;

    if (enable == TRUE)
    {
        _sys_usw_mirror_show_dst_port(lchip, excp_index, session_id, CTC_MIRROR_L2SPAN_SESSION, CTC_EGRESS, 0);
    }

    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "================================================== \n");

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_mirror_show_vlan_info(uint8 lchip, uint16 vlan_id)
{
    uint32 excp_index = 0;
    uint32 session_id = 0;
    uint32 enable = FALSE;
    DsMetFifoExcp_m met_excp;
    ds_t epehdr_adj_exp;
    sal_memset(&met_excp, 0, sizeof(DsMetFifoExcp_m));
    sal_memset(&epehdr_adj_exp, 0, sizeof(ds_t));

    SYS_MIRROR_INIT_CHECK();
    CTC_VLAN_RANGE_CHECK(vlan_id);

    CTC_ERROR_RETURN(sys_usw_vlan_get_internal_property(lchip, vlan_id, SYS_VLAN_PROP_INGRESS_VLAN_SPAN_ID, &session_id));
    CTC_ERROR_RETURN(sys_usw_vlan_get_internal_property(lchip, vlan_id, SYS_VLAN_PROP_INGRESS_VLAN_SPAN_EN, &enable));

    excp_index = MCHIP_CAP(SYS_CAP_MIRROR_INGRESS_L3_SPAN_INDEX_BASE) + session_id;

    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "================================================== \n");
    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-5s %-10s %-10s %-10s %-10s\n", "Type", "Session-ID", "Direction", "Dest-Port", "Nexthop-Ptr");
    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-------------------------------------------------- \n");

    if (enable == TRUE)
    {
        _sys_usw_mirror_show_dst_port(lchip, excp_index, session_id, CTC_MIRROR_L3SPAN_SESSION, CTC_INGRESS, 0);
    }

    enable = FALSE;
    CTC_ERROR_RETURN(sys_usw_vlan_get_internal_property(lchip, vlan_id, SYS_VLAN_PROP_EGRESS_VLAN_SPAN_ID, &session_id));
    CTC_ERROR_RETURN(sys_usw_vlan_get_internal_property(lchip, vlan_id, SYS_VLAN_PROP_EGRESS_VLAN_SPAN_EN, &enable));

    excp_index = MCHIP_CAP(SYS_CAP_MIRROR_EGRESS_L3_SPAN_INDEX_BASE) + session_id;

    if (enable == TRUE)
    {
        _sys_usw_mirror_show_dst_port(lchip, excp_index, session_id, CTC_MIRROR_L3SPAN_SESSION, CTC_EGRESS, 0);
    }

    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "================================================== \n");

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_mirror_show_acl_info(uint8 lchip, uint16 log_id)
{
    uint8  priority_id = 0;
    uint8  max_priority_id = 0;
    uint32 excp_index = 0;
    uint32 cmd = 0;
    uint32 dest_map = 0;
    uint32 direction = 0;
    DsMetFifoExcp_m met_excp;
    ds_t epehdr_adj_exp;
    uint32 acl_log_base[2] = {MCHIP_CAP(SYS_CAP_MIRROR_INGRESS_ACL_LOG_INDEX_BASE), MCHIP_CAP(SYS_CAP_MIRROR_EGRESS_ACL_LOG_INDEX_BASE)};
    uint8 bit_width = DRV_FROM_AT(lchip)? 3 : 0;

    sal_memset(&met_excp, 0, sizeof(DsMetFifoExcp_m));
    sal_memset(&epehdr_adj_exp, 0, sizeof(ds_t));

    SYS_MIRROR_INIT_CHECK();

    if (log_id >= MCHIP_CAP(SYS_CAP_MIRROR_ACL_LOG_ID))
    {
        SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Mirror] Invalid mirror log id \n");
        return CTC_E_BADID;

    }

    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "============================================================= \n");
    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-5s %-10s %-10s %-10s %-10s %-10s\n", "Type", "Session-ID", "Priority", "Direction", "Dest-Port", "Nexthop-Ptr");
    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "------------------------------------------------------------- \n");
    for (direction = 0; direction < 2; direction++)
    {
        if(direction == 0)
        {
            max_priority_id = MCHIP_CAP(SYS_CAP_MIRROR_INGRESS_ACL_LOG_PRIORITY);
        }
        else
        {
            max_priority_id = MCHIP_CAP(SYS_CAP_MIRROR_EGRESS_ACL_LOG_PRIORITY);
        }

        for (priority_id = 0; priority_id < max_priority_id; priority_id++)
        {
            excp_index = acl_log_base[direction] + (MCHIP_CAP(SYS_CAP_MIRROR_ACL_LOG_ID) * priority_id) + log_id;
            cmd = DRV_IOR(DsMetFifoExcp_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, excp_index << bit_width, cmd, &met_excp));
            GetDsMetFifoExcp(A, destMap_f, &met_excp, &dest_map);

            if (SYS_RSV_PORT_DROP_ID == (dest_map & 0x1FF) && GetDsMetFifoExcp(V, unionDestType_f, &met_excp) == 0)
            {

            }
            else
            {
                _sys_usw_mirror_show_dst_port(lchip, excp_index, log_id, CTC_MIRROR_ACLLOG_SESSION, direction, priority_id);
            }
        }
    }
    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "============================================================= \n");

    return CTC_E_NONE;
}

int32
sys_usw_mirror_show_info(uint8 lchip, ctc_mirror_info_type_t type, uint32 value)
{
    int32  ret = CTC_E_NONE;
    SYS_MIRROR_INIT_CHECK();
    if (CTC_MIRROR_INFO_PORT == type)
    {
        SYS_MAP_GPORT_TO_LCHIP(value, lchip);
        MIRROR_LOCK;
        ret = _sys_usw_mirror_show_port_info(lchip, value);
    }
    else
    {
        MIRROR_LOCK;
        if (CTC_MIRROR_INFO_VLAN == type)
        {
            ret = _sys_usw_mirror_show_vlan_info(lchip, value);
        }
        else if (CTC_MIRROR_INFO_ACL == type)
        {
            ret = _sys_usw_mirror_show_acl_info(lchip, value);
        }
        else
        {
            ret = CTC_E_INVALID_PARAM;
        }
    }
    MIRROR_UNLOCK;
    return ret;
}

STATIC int32 _sys_usw_mirror_linklist_delete(uint8* ptr)
{
    if (ptr)
    {
        mem_free(ptr);
    }
    return CTC_E_NONE;
}

int32
_sys_usw_mirror_show_brief_span(uint8 lchip, uint8 type)
{
    uint32   i = 0;
    uint32   j = 0;
    uint32   k = 0;
    uint32   cmd = 0;
    uint32   value = 0;
    ctc_linklist_t* p_list[CTC_BOTH_DIRECTION] = {0};
    ctc_listnode_t*   p_node = NULL;
    uint32* buf = NULL;
    int32  ret = 0;
    uint16 tbl_id = 0;
    uint32 fld_id = 0;
    uint8  span_src_en = 0;
    uint16 srcport_cnt[CTC_BOTH_DIRECTION][MAX_CTC_MIRROR_SESSION_ID];
    uint32 *destport[CTC_BOTH_DIRECTION][MAX_CTC_MIRROR_SESSION_ID];
    uint8  gchip_id = 0;
    uint8  session_max_num = 0;
    uint16 input_tbl[CTC_BOTH_DIRECTION];
    uint32 input_span_en[CTC_BOTH_DIRECTION];
    uint32 input_span_id[CTC_BOTH_DIRECTION];
    uint32 input_excep_base[CTC_BOTH_DIRECTION];
    uint8  string[5] = {0};
    uint8  val_mem_num[CTC_BOTH_DIRECTION][MAX_CTC_MIRROR_SESSION_ID] = {{0}};
    uint8  max_mem_num = MCHIP_CAP(SYS_CAP_MIRROR_MEMBER_NUM);
    uint8  bit_width = DRV_FROM_AT(lchip)? 3 : 0;
    DsMetFifoExcp_m met_fifo ;

    sal_memset(destport, 0, sizeof(void*)*CTC_BOTH_DIRECTION*MAX_CTC_MIRROR_SESSION_ID);
    switch (type)
    {
        case 0:/*l2span*/
            input_tbl[CTC_INGRESS] = DsPhyPortExt_t;
            input_tbl[CTC_EGRESS] = DsDestPort_t;
            input_span_en[CTC_INGRESS] = DsPhyPortExt_l2SpanEn_f;
            input_span_en[CTC_EGRESS] =  DsDestPort_l2SpanEn_f;
            input_span_id[CTC_INGRESS] = DsPhyPortExt_l2SpanId_f;
            input_span_id[CTC_EGRESS] = DsDestPort_l2SpanId_f;
            input_excep_base[CTC_INGRESS] = SYS_CAP_MIRROR_INGRESS_L2_SPAN_INDEX_BASE;
            input_excep_base[CTC_EGRESS] = SYS_CAP_MIRROR_EGRESS_L2_SPAN_INDEX_BASE;
            sal_memcpy(string, "Port", 4);
            session_max_num = 4;
            break;
        case 1:/*l3span*/
            if (!DRV_FROM_TMM(lchip))
            {
                input_tbl[CTC_INGRESS]     =  DsSrcVlanProfile_t;
                input_tbl[CTC_EGRESS]      =  DsDestVlanProfile_t;
                input_span_en[CTC_INGRESS] =  DsSrcVlanProfile_ingressVlanSpanEn_f;
                input_span_en[CTC_EGRESS]  =  DsDestVlanProfile_egressVlanSpanEn_f;
                input_span_id[CTC_INGRESS] =  DsSrcVlanProfile_ingressVlanSpanId_f;
                input_span_id[CTC_EGRESS]  =  DsDestVlanProfile_egressVlanSpanId_f;
            }
            else
            {
                input_tbl[CTC_INGRESS]     =  DsSrcVlan_t;
                input_tbl[CTC_EGRESS]      =  DsDestVlan_t;
                input_span_en[CTC_INGRESS] =  DsSrcVlan_ingressVlanSpanEn_f;
                input_span_en[CTC_EGRESS]  =  DsDestVlan_egressVlanSpanEn_f;
                input_span_id[CTC_INGRESS] =  DsSrcVlan_ingressVlanSpanId_f;
                input_span_id[CTC_EGRESS]  =  DsDestVlan_egressVlanSpanId_f;
            }
            input_excep_base[CTC_INGRESS] = SYS_CAP_MIRROR_INGRESS_L3_SPAN_INDEX_BASE;
            input_excep_base[CTC_EGRESS]  = SYS_CAP_MIRROR_EGRESS_L3_SPAN_INDEX_BASE;
            sal_memcpy(string, "Vlan", 4);
            session_max_num = 4;
            break;
        case 2:/*cpu mirror*/
            if (!DRV_FROM_TMM(lchip))
            {
                input_tbl[CTC_INGRESS]     =  BufferStoreCtl_t;
                input_tbl[CTC_EGRESS]      =  BufferStoreCtl_t;
                input_span_en[CTC_INGRESS] =  BufferStoreCtl_cpuRxExceptionEn0_f;
                input_span_en[CTC_EGRESS]  =  BufferStoreCtl_cpuTxExceptionEn_f;
            }
            else
            {
                input_tbl[CTC_INGRESS]     =  IpeCpuRxTxExceptionCtl_t;
                input_tbl[CTC_EGRESS]      =  IpeCpuRxTxExceptionCtl_t;
                input_span_en[CTC_INGRESS] =  IpeCpuRxTxExceptionCtl_cpuRxExceptionEn0_f;
                input_span_en[CTC_EGRESS]  =  IpeCpuRxTxExceptionCtl_cpuTxExceptionEn_f;
            }
            input_span_id[CTC_INGRESS] =  0;
            input_span_id[CTC_EGRESS]  =  0;
            input_excep_base[CTC_INGRESS] = SYS_CAP_MIRROR_CPU_RX_SPAN_INDEX;
            input_excep_base[CTC_EGRESS]  = SYS_CAP_MIRROR_CPU_TX_SPAN_INDEX;
            sal_memcpy(string, "CPU", 4);
            session_max_num = 1;
            break;
        default:
            return 0;
    }

    sys_usw_get_gchip_id(lchip, &gchip_id);

    for (i=0;i<CTC_BOTH_DIRECTION;i++)
    {
        for (j=0;j<MAX_CTC_MIRROR_SESSION_ID;j++)
        {
            destport[i][j] = mem_malloc(MEM_MIRROR_MODULE, sizeof(uint32)*MCHIP_CAP(SYS_CAP_MIRROR_MEMBER_NUM));
            if(NULL == destport[i][j])
            {
                ret = CTC_E_NO_MEMORY;
                goto done;
            }
            sal_memset(destport[i][j], 0, sizeof(uint32)*MCHIP_CAP(SYS_CAP_MIRROR_MEMBER_NUM));
        }
    }

    sal_memset(srcport_cnt, 0, sizeof(uint16)*MAX_CTC_MIRROR_SESSION_ID*CTC_BOTH_DIRECTION);

    p_list[CTC_INGRESS] = ctc_list_create( NULL, (ctc_list_del_cb_t )_sys_usw_mirror_linklist_delete);
    if (p_list[CTC_INGRESS] == NULL)
    {
        ret = CTC_E_NO_MEMORY;
        goto done;
    }

    p_list[CTC_EGRESS] = ctc_list_create( NULL, (ctc_list_del_cb_t) _sys_usw_mirror_linklist_delete);
    if (p_list[CTC_EGRESS] == NULL)
    {
        ret = CTC_E_NO_MEMORY;
        goto done;
    }

    /*Read Mirror src table */
    for (j = CTC_INGRESS; j < CTC_BOTH_DIRECTION; j++)
    {
        tbl_id = input_tbl[j];
        for (i = 0; i< DRV_TABLE_MAX_INDEX(lchip, tbl_id); i++)
        {
            value = 0;
            cmd = DRV_IOR(tbl_id, input_span_en[j]);
            CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, i, cmd, &value) , ret, done);
            if (value == 0)
            {
                continue;
            }

            buf = (uint32*)mem_malloc(MEM_MIRROR_MODULE, sizeof(uint32)*2);/*uint32-1 <-> gport; uint32-2 <-> spanid*/
            if (buf == NULL)
            {
                ret = CTC_E_NO_MEMORY;
                goto done;
            }
            if (type != 2 )
            {
                cmd = DRV_IOR(tbl_id, input_span_id[j]);
                CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, i, cmd, &value), ret, done);
                if (1 == type)
                {
                    buf[0] = i; /* TM DUET2: profile id, TMM: vlan id */
                }
                else
                {
                    buf[0] = SYS_MAP_DRV_LPORT_TO_CTC_GPORT(gchip_id, i);/*gport*/
                }
                buf[1] = value;/*spanid*/
            }
            else
            {
                value = 0;/*spanid*/
            }
            srcport_cnt[j][value] ++;
            ctc_listnode_add(p_list[j], buf);
            span_src_en = 1;
        }
    }

    /*Read Mirror dest table*/
    for (j = CTC_INGRESS; j < CTC_BOTH_DIRECTION; j++)
    {
        for (i = 0; i < session_max_num ; i++)
        {
            tbl_id = MCHIP_CAP(input_excep_base[j]) + i;
            tbl_id <<= bit_width;
            for (k = 0; k < max_mem_num; k++)
            {
                cmd = DRV_IOR(DsMetFifoExcp_t, DRV_ENTRY_FLAG);
                CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_id, cmd, &met_fifo), ret, done);

                if ((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)) && GetDsMetFifoExcp(V, unionDestType_f, &met_fifo))
                {
                    ctc_mirror_dest_t mirror;
                    sys_mirror_dest_node_t* dest_node = NULL;
                    sal_memset(&mirror, 0, sizeof(ctc_mirror_dest_t));

                    mirror.session_id = i;
                    mirror.type = (2 == type ? 3 : type);
                    mirror.dir = j;

                    dest_node = _sys_usw_mirror_get_db_info(lchip, &mirror, k);
                    destport[j][i][k] = CTC_MAP_TID_TO_GPORT(dest_node->linkagg_id);
                }
                else
                {
                    value = GetDsMetFifoExcp(V, destMap_f, &met_fifo);
                    if (SYS_DESTMAP_IS_CPU(value))
                    {
                        destport[j][i][k] = 0xffff;
                    }
                    else
                    {
                        destport[j][i][k] = SYS_USW_DESTMAP_TO_DRV_GPORT(value);
                        destport[j][i][k] = SYS_MAP_DRV_GPORT_TO_CTC_GPORT(destport[j][i][k]);
                        if (SYS_IS_DROP_PORT(destport[j][i][k]))
                        {
                            break;
                        }
                    }
                }
                tbl_id++;
            }
            val_mem_num[j][i] = (0 == k? k + 1 : k);
        }
    }
    /*dump*/
    if (span_src_en == 0)
    {
        goto done;
    }

    /*per session*/
    for (i = 0; i < session_max_num; i++)
    {
        /*session disable-> continue*/
        if ((srcport_cnt[CTC_INGRESS][i] == 0) && (srcport_cnt[CTC_EGRESS][i] == 0))
        {
            continue;
        }
        for (j = CTC_INGRESS; j < CTC_BOTH_DIRECTION; j++)
        {
            CTC_LIST_LOOP(p_list[j], buf, p_node)
            {
                if ((buf[1] == i) && (type == 0))
                {
                    for (k = 0; k < val_mem_num[j][i]; k++)
                    {
                        SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-5s %-10d %-10s 0x%-.4x     ", string, i,  (j == CTC_INGRESS ? "Ingress" : "Egress"), buf[0]);
                        if (destport[j][i][k] == 0xffff)
                        {
                            SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "CPU\n");
                        }
                        else
                        {
                            SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "0x%-.4x\n", destport[j][i][k]);
                        }
                    }
                }
                if ((buf[1] == i) && (type == 1))
                {
                    if (DRV_FROM_TMM(lchip))
                    {
                        for (k = 0; k < val_mem_num[j][i]; k++)
                        {
                            SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-5s %-10d %-10s 0x%-.4x     ", string, i,  (j == CTC_INGRESS ? "Ingress" : "Egress"), buf[0]);
                            if (destport[j][i][k] == 0xffff)
                            {
                                SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "CPU\n");
                            }
                            else
                            {
                                SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "0x%-.4x\n", destport[j][i][k]);
                            }
                        }
                    }
                    else
                    {
                        tbl_id = (j == CTC_INGRESS ? DsSrcVlan_t : DsDestVlan_t);
                        fld_id = (j == CTC_INGRESS ? DsSrcVlan_profileId_f : DsDestVlan_profileId_f);
                        for (k = 0; k < DRV_TABLE_MAX_INDEX(lchip, tbl_id); k++)
                        {
                            value = 0;
                            cmd = DRV_IOR(tbl_id, fld_id);
                            CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, k, cmd, &value) , ret, done);
                            if (value == buf[0] && !DRV_FROM_TMM(lchip))
                            {
                                SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-5s %-10d %-10s 0x%-.4x     ", string, i,  (j == CTC_INGRESS ? "Ingress" : "Egress"), k);
                                if (destport[j][i][0] == 0xffff)
                                {
                                    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "CPU\n");
                                }
                                else
                                {
                                    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "0x%-.4x\n", destport[j][i][0]);
                                }
                            }
                        }
                    }
                }
            }
            if (srcport_cnt[j][i] && (type == 2 ))
            {
                for (k = 0; k < val_mem_num[j][i]; k++)
                {
                    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-5s %-10d %-10s %-10s ", string,  i,  (j == CTC_INGRESS ? "Ingress" : "Egress"), "-");
                    if (destport[j][i][k] == 0xffff)
                    {
                        SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "CPU\n");
                    }
                    else
                    {
                        SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "0x%-.4x\n", destport[j][i][k]);
                    }
                }
            }

            if (0 == srcport_cnt[j][i])
            {
                continue;
            }

            if (type == 1)
            {
                continue;
            }
        }
    }


done:
    if (p_list[CTC_INGRESS] != NULL)
    {
        ctc_list_delete(p_list[CTC_INGRESS]);
    }
    if (p_list[CTC_EGRESS] != NULL)
    {
        ctc_list_delete(p_list[CTC_EGRESS]);
    }

    for (i=0;i<CTC_BOTH_DIRECTION;i++)
    {
        for (j=0;j<MAX_CTC_MIRROR_SESSION_ID;j++)
        {
            mem_free(destport[i][j]);
        }
    }

    return ret;
}


int32
sys_usw_mirror_show_brief(uint8 lchip)
{
    SYS_MIRROR_INIT_CHECK();
    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "================================================ \n");
    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-5s %-10s %-10s %-10s %-10s\n", "Type", "Session-ID", "Direction", "SRC", "DEST-PORT");
    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "------------------------------------------------ \n");
    CTC_ERROR_RETURN(_sys_usw_mirror_show_brief_span(lchip, 0));
    CTC_ERROR_RETURN(_sys_usw_mirror_show_brief_span(lchip, 1));
    CTC_ERROR_RETURN(_sys_usw_mirror_show_brief_span(lchip, 2));
    SYS_MIRROR_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "================================================ \n");
    return CTC_E_NONE;
}

